Se você tiver um aplicativo de thread único, poderá usar uma simples tentativa / captura na função Principal, no entanto, isso não cobre exceções que podem ser lançadas fora da função Principal, em outros threads, por exemplo (como observado em outros comentários). Este código demonstra como uma exceção pode causar o encerramento do aplicativo, mesmo que você tenha tentado manipulá-lo no Main (observe como o programa sai normalmente se você pressionar enter e permitir que o aplicativo saia normalmente antes que a exceção ocorra, mas se você permitir a execução , termina bastante infeliz):
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;
}
}
Você pode receber uma notificação de quando outro encadeamento lança uma exceção para executar alguma limpeza antes da saída do aplicativo, mas, pelo que sei, não é possível, a partir de um aplicativo de console, forçar o aplicativo a continuar em execução se você não manipular a exceção no encadeamento do qual ele é lançado sem usar algumas opções de compatibilidade obscuras para fazer com que o aplicativo se comporte como no .NET 1.x. Este código demonstra como o thread principal pode ser notificado sobre exceções provenientes de outros threads, mas ainda será finalizado infelizmente:
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;
}
}
Portanto, na minha opinião, a maneira mais limpa de lidar com isso em um aplicativo de console é garantir que cada encadeamento tenha um manipulador de exceções no nível raiz:
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()
ou qualquer outra perturbação do fluxo de programa, mas o que eu recebo é a exceção re-levantar de novo e de novo, e de novo..