C# Winforms应用程序在未处理的异常处理程序后仍会崩溃
我已经在测试应用程序中应用了这些处理程序:C# Winforms应用程序在未处理的异常处理程序后仍会崩溃,c#,winforms,async-await,C#,Winforms,Async Await,我已经在测试应用程序中应用了这些处理程序: Application.ThreadException += Application_ThreadException; Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException
Application.ThreadException += Application_ThreadException;
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
然后,我在表单上的嵌套任务/Async Wait上创建了一个异常:
尽管启动了处理程序-CurrentDomain.UnhandledException
,但应用程序仍会崩溃
为什么它会崩溃而不显示对话框并保持运行
未处理System.Exception
消息:mscorlib.dll中发生类型为“System.exception”的未处理异常
其他信息:dd
编辑:
看起来我忘记了用Task声明每个异步方法,而不是void,因此异常处理现在可以预料到了。唯一我仍然不知道的是,如果我停止处理按钮事件中的异常,为什么会在异常被捕获时触发
Application\u ThreadException
,而不是TaskScheduler\u unobservedtaskeexception
我不确定您是否解决了问题?
如果关键是捕获未绑定的异常,那么您可以这样做。
在应用程序之前添加到program.cs。运行
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
创建2个空隙以处理异常数据
static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message, "Unhandled Thread Exception");
// here you can log the exception ...
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show((e.ExceptionObject as Exception).Message, "Unhandled UI Exception");
// here you can log the exception ...
}
您的原始代码做了一些您永远不应该做的事情:调用
async void
方法。有问题的异常处理是原因之一
让我们逐一查看事件处理程序:
仅处理Winforms UI线程上的异常。异常从未到达UI线程,因此不会触发此事件Application.ThreadException
仅处理来自TaskScheduler.unobservedtaskeexception
s的未观察到的异常(即使如此,当它们最终确定时也是如此,如果您没有分配太多内存,这可能需要很长时间)。但是未观察到的异常与任何Task
任务都没有关联,因此也不会触发
处理在前两个事件处理程序之后仍被视为未观察到的所有异常。但它不能用于设置观察到的异常,因此应用程序仍然终止。这是唯一一个实际触发的处理程序AppDomain.CurrentDomain.UnhandledException
Task.Run(()=>new IGetRun().Run1())
,其中Run1()
是一个async void
方法,该方法引发异常
当async void
方法中存在未观察到的异常时,将在当前同步上下文中重新引发该异常。但是,由于该方法在线程池线程上运行(由于Task.Run()
),因此不存在同步上下文。因此,在线程池线程上引发异常,前两个事件处理程序无法观察到该异常
正如您已经发现的,解决此问题的方法是使用async Task
方法并正确地等待它们
在更新的代码中,
Run1()
现在是一个异步任务
方法。该任务
由Task.Run()
展开,然后等待
ed,因此异常被转移到Hello()
任务
。依次从UI线程上的async void按钮1u单击handler执行wait
ed
这都意味着不存在未观察到的任务
异常,并且在UI同步上下文中重新引发异常。在Winforms中,这意味着应用程序。会引发ThreadException
,这正是您所观察到的。可能是@JMK的一个副本,无法充分回答我的问题。因此使用了“潜在”一词@JMK我是否错误地认为您投票关闭了我的问题?我注意到您在代码中使用线程,并且认为这可能与异常被抛出到一个线程中,而不是被另一个线程捕获有关,这是常见的问题,因此投票结果接近。没有其他人投票赞成关闭,虽然看起来我错了。嗨,我确实解决了最初的问题,通过确保任务中使用的异步方法在调用堆栈的所有签名中都不无效来处理未处理的异常。我的突出问题是不知道为什么不调用TaskScheduler\u UnobservedTaskException而不是Application\u ThreadException。真棒的答案:)我希望所有的答案都像这个一样完整。@s单击“谢谢”和“+1”,但您能回答我附录中的问题吗?假设按钮处理程序中没有try/catch,并且始终使用异步任务。我没有观察到任何任务异常,因此希望TaskScheduler.UnobservedTaskException在延迟后运行,但调用了应用程序\u ThreadException。也许我需要一个新问题…@Jaycee请参阅更新。您正在使用wait
或Task.Run()
观察所有Task
异常。
static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message, "Unhandled Thread Exception");
// here you can log the exception ...
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MessageBox.Show((e.ExceptionObject as Exception).Message, "Unhandled UI Exception");
// here you can log the exception ...
}