Se si dispone di un'applicazione a thread singolo, è possibile utilizzare un semplice tentativo / catch nella funzione Main, tuttavia, ciò non copre le eccezioni che possono essere generate al di fuori della funzione Main, ad esempio su altri thread (come notato in altri Commenti). Questo codice dimostra come un'eccezione può causare la chiusura dell'applicazione anche se si è tentato di gestirla in Main (notare come il programma si chiude correttamente se si preme invio e si consente all'applicazione di uscire con grazia prima che si verifichi l'eccezione, ma se la si lascia eseguire , termina abbastanza infelice):
static bool exiting = false;
static void Main(string[] args)
{
try
{
System.Threading.Thread demo = new System.Threading.Thread(DemoThread);
demo.Start();
Console.ReadLine();
exiting = true;
}
catch (Exception ex)
{
Console.WriteLine("Caught an exception");
}
}
static void DemoThread()
{
for(int i = 5; i >= 0; i--)
{
Console.Write("24/{0} =", i);
Console.Out.Flush();
Console.WriteLine("{0}", 24 / i);
System.Threading.Thread.Sleep(1000);
if (exiting) return;
}
}
È possibile ricevere una notifica di quando un altro thread genera un'eccezione per eseguire un po 'di pulizia prima che l'applicazione venga chiusa, ma per quanto ne so, non è possibile, da un'applicazione console, forzare l'applicazione a continuare l'esecuzione se non si gestisce l'eccezione sul thread da cui viene generato senza utilizzare alcune oscure opzioni di compatibilità per far sì che l'applicazione si comporti come avrebbe fatto con .NET 1.x. Questo codice dimostra come il thread principale può essere informato delle eccezioni provenienti da altri thread, ma terminerà comunque infelice:
static bool exiting = false;
static void Main(string[] args)
{
try
{
System.Threading.Thread demo = new System.Threading.Thread(DemoThread);
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
demo.Start();
Console.ReadLine();
exiting = true;
}
catch (Exception ex)
{
Console.WriteLine("Caught an exception");
}
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Console.WriteLine("Notified of a thread exception... application is terminating.");
}
static void DemoThread()
{
for(int i = 5; i >= 0; i--)
{
Console.Write("24/{0} =", i);
Console.Out.Flush();
Console.WriteLine("{0}", 24 / i);
System.Threading.Thread.Sleep(1000);
if (exiting) return;
}
}
Quindi secondo me, il modo più pulito per gestirlo in un'applicazione console è garantire che ogni thread abbia un gestore di eccezioni a livello di root:
static bool exiting = false;
static void Main(string[] args)
{
try
{
System.Threading.Thread demo = new System.Threading.Thread(DemoThread);
demo.Start();
Console.ReadLine();
exiting = true;
}
catch (Exception ex)
{
Console.WriteLine("Caught an exception");
}
}
static void DemoThread()
{
try
{
for (int i = 5; i >= 0; i--)
{
Console.Write("24/{0} =", i);
Console.Out.Flush();
Console.WriteLine("{0}", 24 / i);
System.Threading.Thread.Sleep(1000);
if (exiting) return;
}
}
catch (Exception ex)
{
Console.WriteLine("Caught an exception on the other thread");
}
}
Console.ReadLine()
o nessun altro disturbo del flusso del programma. Ma quello che ottengo è l'eccezione che si ripropone ancora e ancora e ancora.