正在抑制应用程序.ThreadException和AppDomain.CurrentDomain.未处理的异常

本文关键字:CurrentDomain AppDomain 未处理 异常 ThreadException 应用程序 | 更新日期: 2023-09-27 17:58:51

我已经编写了一个WinForms应用程序,它可以执行某种同步工作。我希望它在出现任何异常的情况下都能继续运行,以便在下次尝试时继续同步。因此,我编写该应用程序的方式是,每当发生异常时,它都会记录异常堆栈跟踪,执行一些诊断,然后记录诊断信息,并继续进行下一次同步尝试。

对于未捕获的异常,我在Main()线程中为Application.ThreadExceptionAppDomain.CurrentDomain.UnhandledException添加了异常处理程序:

static void Main(string[] args)
{    
    Application.ThreadException += new ThreadExceptionEventHandler(UIThreadExceptionHandler);
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
    AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(UnhandledExceptionHandler);

    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new myForm());
}

//exception handlers
 public static void UIThreadExceptionHandler(object sender, ThreadExceptionEventArgs t)
 {
     logger.Fatal("Fatal Windows Forms Error");
     logStackTrace(t.Exception);                    //logs the stack trace with some desired formatting  
     Application.Exit(new CancelEventArgs(true));
 }
 public static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs t) 
 {
     logger.Fatal("Fatal Application Error");
     logStackTrace((Exception)(t.ExceptionObject)); //logs the stack trace with some desired formatting           
     Application.Exit(new CancelEventArgs(true));
 }

我一直在运行我的应用程序进行测试,并意识到每当捕获到Application.ThreadException时,应用程序都会正确地记录字符串Fatal Windows Forms Error,然后是异常堆栈跟踪,然后应用程序就会退出。

我不希望应用程序退出。我只想它应该记录异常堆栈跟踪并继续下一次同步尝试。UI线程中发生的异常并不是那么严重,因为同样的异常也发生在应用程序的其他/非UI线程中,但它并没有使应用程序崩溃(正如我在日志中看到的那样)。但是,当UI线程中发生相同的异常时,应用程序将崩溃。

正在抑制应用程序.ThreadException和AppDomain.CurrentDomain.未处理的异常

因为它是windows窗体应用程序。ThreadException用于未处理的异常:"此事件允许您的Windows窗体应用程序处理Windows窗体线程中发生的未处理异常。将事件处理程序附加到ThreadException事件以处理这些异常"(MSDN)

我认为您必须期待这样的行为,比如在UIThreadExceptionHandler中您有Application。退出(新的CancelEventArgs(true))。退出方法描述:"通知所有消息泵它们必须终止,然后在处理完消息后关闭所有应用程序窗口。"(MSDN)

AppDomain。CurrentDomain。UnhandledException事件用于处理非UI线程异常。

第1版:

AppDomain。CurrentDomain。UnhandledException专门用于在系统通知用户并终止进程之前记录异常。您无法阻止终止进程(除非您使用Net 1.1)。

应用程序。ThreadException+未处理的异常模式。CatchException允许您保持UI线程的活力。但是,这真的不是一个好主意。将容易出错的代码封装在try-catch块中要好得多。

因此,如果您想捕获来自线程的异常并保持应用程序的活力,就必须在内部使用try-catch块。

您对UnhandledExceptionHandler没有异议,因为我想它根本没有被激发。

Windows Forms并不是为应用程序需要无限期运行的场景而设计的。正如您所经历的,当您截获某些异常时,您的应用程序已经被吸入黑洞,您无法阻止应用程序的死亡。

我认为更好的方法是使用具有两个线程的Windows服务:前台监视器线程和后台工作线程(使用BackgroundWorker类型)。工人线程是你的不合时宜的工作发生的地方。当工作线程由于未处理的异常而终止时,监视线程会记录该异常并重新启动工作线程。

如果情况严重到监视器线程也会死亡(例如OutOfMemoryException或ExecutionEngineException),那么服务本身就会死亡。但是,您可以将服务控制管理器设置为在该事件中重新启动服务。

如果您需要某种用户交互,您还可以创建一个Windows窗体应用程序,该应用程序可以与您的新服务对话并启动/停止它