我编写了一个WinForms应用程序,它执行某种同步工作。我希望它能够继续运行,尽管出现异常,以便同步继续进行下一次尝试。因此,我编写了应用程序,只要发生异常,它就会记录异常堆栈跟踪,执行一些诊断,然后记录诊断信息并继续下一次同步尝试。
对于未捕获的异常,我在Application.ThreadException
主题中为AppDomain.CurrentDomain.UnhandledException
和Main()
添加了异常处理程序:
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线程中发生相同的异常时,应用程序崩溃。
答案 0 :(得分:0)
因为它的Windows窗体应用程序Application.ThreadException用于非公开异常:"此事件允许您的Windows窗体应用程序处理Windows窗体线程中出现的其他未处理的异常。将事件处理程序附加到ThreadException事件以处理这些异常" (MSDN)
我认为你必须期望在UIThreadExceptionHandler这样的行为你有Application.Exit(new CancelEventArgs(true))。退出方法说明:"通知所有消息泵必须终止,然后在处理完消息后关闭所有应用程序窗口。" (MSDN)
AppDomain.CurrentDomain.UnhandledException事件用于处理非UI线程异常。
编辑1:
AppDomain.CurrentDomain.UnhandledException 专门用于在系统通知用户并终止进程之前记录异常。您无法阻止终止该过程(除非您使用的是Net 1.1)。
Application.ThreadException + UnhandledExceptionMode.CatchException 允许您保持UI线程的活动。但是,这真的不是一个好主意。将错误倾向代码包含在try-catch块中会好得多。
因此,如果你想捕获来自线程的异常并使应用程序保持活动状态,你必须使用try-catch块来实现它。
我还没有问过UnhandledExceptionHandler,因为它根本没有被解雇,我想。
答案 1 :(得分:0)
Windows Forms并非真正针对应用程序需要无限期运行的场景而设计。正如您所经历的那样,当您截获某些例外情况时,您的应用程序已经陷入了黑洞,您无法阻止您的应用程序死亡。
我认为更好的方法是使用具有两个线程的Windows服务:前台监视器线程和后台工作线程(使用BackgroundWorker类型)。工作线程是您的同步工作发生的地方。当工作线程由于未处理的异常而死亡时,监视器线程会记录异常并重新启动工作线程。
如果情况非常糟糕,监视器线程也会死掉(例如OutOfMemoryException或ExecutionEngineException),那么服务本身就会死掉。但您可以将服务控制管理器设置为在该事件中重新启动服务。
如果您需要某种用户交互性,您还可以创建一个与您的新服务对话并启动/停止它的Windows窗体应用程序。