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
方法。有问题的异常处理是原因之一

让我们逐一查看事件处理程序:

  • Application.ThreadException
    仅处理Winforms UI线程上的异常。异常从未到达UI线程,因此不会触发此事件
  • TaskScheduler.unobservedtaskeexception
    仅处理来自
    Task
    s的未观察到的异常(即使如此,当它们最终确定时也是如此,如果您没有分配太多内存,这可能需要很长时间)。但是未观察到的异常与任何
    任务都没有关联,因此也不会触发
  • 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 ...
}