Application.ThreadException vs AppDomain.UnhandledException
本文关键字:UnhandledException AppDomain vs ThreadException Application | 更新日期: 2023-09-27 17:57:29
首先介绍一些背景:我有一个多线程WinForms应用程序,它正在对本机dll进行互操作。这个应用程序有时会因未处理的异常而崩溃,我们正在努力调查为什么会发生这种情况。为了方便它,我正在创建一个全局异常处理程序,并计划从中生成进程转储文件
现在问题来了:到目前为止,这个应用程序有Application.ThreadException
的处理程序,但它仍然会因未处理的异常而崩溃。我也在考虑为AppDomain.UnhandledException
添加一个处理程序,尽管我不确定它是否会有所帮助。在这种情况下,是否有任何可能的未处理的异常不会被Application.ThreadException
捕获?
它所做的而不是陷阱是在任何非UI线程上引发的异常,例如用thread.Start()、ThreadPool.QueueUserWorkItem或委托的BeginInvoke()方法启动的工作线程。其中任何未处理的异常都将终止应用程序,AppDomain.UnhandledException是最后一搏。
更深入地说,从未进行过任何托管CLR调用的本机代码在非托管线程中引发的硬件异常无法用任何CLR机制检测到。AccessViolation(异常代码0xc0000005)是最常见的死亡原因。捕获它们的唯一方法是通过Windows API SetUnhandledExceptionFilter()。这很难做到正确。
您可以使用Application.SetUnhandledExceptionMode()禁用Application.ThreadException。明智的做法是,给用户提供"继续"选项没有多大意义。现在,托管线程中的所有异常行为都相同,请使用AppDomain.UnhandledException对其进行日志记录。
Application.ThreadException
将仅针对WinForms UI线程上未处理的异常而引发(请参阅此处。)在这种情况下,为AppDomain.UnhandledException
添加处理程序可能会有所帮助(尽管有一些注意事项,如此处备注部分所述。)
我强烈建议您使用操作系统小型转储生成,而不是自己的。这有几个原因:
- 在同一进程中生成小型转储是非常有问题的,而且并不总是可能的
- 当
ThreadException
或UnhandledException
启动时,异常堆栈已经展开。在这一点上生成一个小型转储只会指向处理程序,而不是异常的源
如果您的应用程序在现场,请使用WER。如果您正在进行内部测试,请使用ProcDump。您也可以在"错误报告"对话框处于活动状态时复制小型转储文件。
附言:有一些特殊情况,尤其是在执行p/Invoke时,ThreadException
和UnhandledException
都不起作用。
p.p.S.如果有可调试的场景,请尝试打开与p/Invoke相关的托管调试助手。