AppDomain.UnhandledException 自动重新抛出已处理的异常
Posted
技术标签:
【中文标题】AppDomain.UnhandledException 自动重新抛出已处理的异常【英文标题】:AppDomain.UnhandledException automatically re-throws handled exception 【发布时间】:2013-02-02 18:44:21 【问题描述】:我试图在我的应用程序中捕获所有未处理的异常,以便有条件地处理那些可以在不终止应用程序的情况下发生的异常,但我无法解决一个非常基本的问题:它不会停止异常。未处理的异常在代码中的某处被抛出,它来到这里,显示消息框,然后应用程序要么显示相同的异常未处理(如果处于调试模式),要么只是崩溃(如果运行时没有调试)。这意味着即使调用了处理程序,异常仍处于未处理状态。
App()
AppDomain.CurrentDomain.UnhandledException += (s, a) =>
var ex = (Exception)a.ExceptionObject;
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
;
这是来自一个新的空白测试项目,其中只有这段代码和一个在单击时引发异常的按钮。
【问题讨论】:
【参考方案1】:您忘记终止程序。所以它继续进行正常的未处理异常处理。添加这一行:
Environment.Exit(System.Runtime.InteropServices.Marshal.GetHRForException(ex));
稍微费力的 Marshal 调用可确保为您的进程获取 Process.ExitCode 的另一个进程获得合理的错误指示。它是可选的,仅推荐。
【讨论】:
【参考方案2】:From MSDN:
此事件提供未捕获异常的通知。它允许应用程序在系统默认处理程序向用户报告异常并终止应用程序之前记录有关异常的信息。如果有关应用程序状态的足够信息可用,则可以采取其他措施——例如保存程序数据以供以后恢复。建议小心,因为如果不处理异常,程序数据可能会损坏。
换句话说,它只是一个处理程序,可让您告诉用户发生了什么,在您需要恢复数据时生成最后一分钟的保存信息,或者执行诸如触发自定义错误报告之类的操作。 它不是一个 catch 块。要捕获异常,您必须使用 Try-Catch。
【讨论】:
谢谢,虽然这只是意味着我回到了第一个问题 - 如何设置全局(多线程支持)异常处理程序。 我对多线程了解不多,但我怀疑您只需要 Try-Catch 每个线程的根方法。无论如何,这将使您能够更好地控制如何在逐个线程的基础上处理异常,因为可能每个线程都在做不同的事情,这将需要不同的处理。【参考方案3】:如果这确实是您想要的行为,您可以将以下内容添加到您的应用程序配置文件中:
<legacyUnhandledExceptionPolicy enabled="1"/>
见Exceptions in Managed Threads。
【讨论】:
如果我正确理解了 MSDN 文档,这也将使后台线程中任何未处理的异常都被静默处理。这对我不起作用,我需要一种方法来捕获(并有条件地处理)所有未处理的异常,无论它们在哪里被抛出。 @ModusOperandi 我不明白。你有没有尝试过?我的理解是UnhandledException
仍会捕获异常,但它们只是不会终止进程。您可以评估您的异常,并在必要时终止。【参考方案4】:
它不应该“停止”异常,即行为is by design:
此事件提供未捕获异常的通知。它允许应用程序在系统默认处理程序向用户报告异常并终止应用程序之前记录有关异常的信息。
考虑到这个地方没有其他人费心处理有问题的异常,除了记录和死亡之外别无明智之举。
您应该处理那些应该在更接近它们发生的地方终止应用程序的异常。
【讨论】:
【参考方案5】:您实际上并没有捕获未处理的异常,而只是处理在终止应用程序之前发生的事件(在发布模式下)。订阅此事件不算捕捉到已经未处理的异常。
来自MSDN: 此事件提供未捕获异常的通知。它允许应用程序在系统默认处理程序向用户报告异常并终止应用程序之前记录有关异常的信息。如果有关应用程序状态的足够信息可用,则可以采取其他措施——例如保存程序数据以供以后恢复。建议小心,因为如果不处理异常,程序数据可能会损坏。
【讨论】:
以上是关于AppDomain.UnhandledException 自动重新抛出已处理的异常的主要内容,如果未能解决你的问题,请参考以下文章