Если у вас однопоточное приложение, вы можете использовать простой try / catch в функции Main, однако это не распространяется на исключения, которые могут быть выброшены вне функции Main, например, в других потоках (как отметил в других комментариях). Этот код демонстрирует, как исключение может привести к завершению работы приложения, даже если вы пытались обработать его в Main (обратите внимание, как программа корректно завершает работу, если вы нажмете Enter и разрешите приложению корректно завершить работу до возникновения исключения, но если вы позволите ему работать оканчивается довольно печально):
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;
}
}
Вы можете получить уведомление о том, что другой поток выдает исключение для выполнения некоторой очистки перед выходом из приложения, но, насколько я могу судить, из консольного приложения вы не можете заставить приложение продолжать работать, если вы этого не сделаете. обработать исключение в потоке, из которого оно выброшено, без использования некоторых непонятных параметров совместимости, чтобы заставить приложение вести себя так, как это было бы с .NET 1.x. Этот код демонстрирует, как основной поток может быть уведомлен об исключениях, поступающих из других потоков, но все равно будет прерван к несчастью:
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;
}
}
Так что, на мой взгляд, самый простой способ справиться с этим в консольном приложении - убедиться, что каждый поток имеет обработчик исключений на корневом уровне:
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");
}
}