【问题标题】:Can a global exception handler deal with exceptions in an awaited function?全局异常处理程序可以处理等待函数中的异常吗?
【发布时间】:2018-08-29 19:15:10
【问题描述】:

我有一个 WPF 桌面应用程序,它在后台线程中调用任务,如下所示:

private async void SomeButton_Click(object sender, EventArgs e)
{
  await Task.Run(async () =>
  {
    await DoSomething();
  });      
}

public async Task DoSomething()
{
  //do something that throws an exception, mocked like this
  throw new Exception("Test");
}

我在 App 启动中有这样的顶级异常处理程序:

this.Dispatcher.UnhandledException += OnDispatcherUnhandledException;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;

这些处理程序都只是将异常记录到文件中。

如果我将 DoSomething 的全部内容放在 try/catch 块中,catch 起作用并且任务完成。

但如果抛出了不在 try/catch 中的异常,则将调用 CurrentDomain_UnhandledException 处理程序,但 IsTerminating 属性为 true 并且应用程序崩溃。 p>

如何设置一个全局异常处理程序来处理异常而不使我的进程崩溃,而不必在可能在非调度程序线程上调用的每个方法中放置 try/catch 处理?

【问题讨论】:

  • 在您的示例代码中,DoSomething() 方法只是在调度程序线程上引发异常,然后应首先调用 OnDispatcherUnhandledException 处理程序。这真的是你在做什么还是只是一个坏例子?
  • 是的,不好的例子。更新代码以显示实际问题。
  • 我更改了代码以显示从非调度程序线程调用DoSomething 的简单方法。这是真正的问题;正如您所意识到的,另一个确实抛出了Dispatcher.UnhandledException,这很容易处理。
  • 您应该在每个 await 周围放置一个 try/catch,即在示例代码中的 SomeButton_Click 中。 await 传播 Task.Run 捕获的异常。
  • 嗯,确实有效。但这意味着您不能真正拥有全局处理程序;您需要手动处理每个这样的代码块,这是不可取的。能够全局设置它会更好,这样它们都可以用相同的代码处理,所以如果你错过了一个,它不会导致应用程序崩溃。

标签: .net wpf multithreading exception-handling


【解决方案1】:

OnDispatcherUnhandledException 事件处理程序中,您应该将Handled 属性设置为true

private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
   // log
   e.Handled = true;
}

【讨论】:

  • 我的示例代码很糟糕。我更新显示DoSomething 代码正在非调度程序线程中调用。这就是我实际上正在做的事情,除非在 try/catch 块中,否则它会使应用程序崩溃。
猜你喜欢
  • 2011-04-07
  • 1970-01-01
  • 2014-04-17
  • 2012-12-31
  • 2011-05-19
  • 2011-08-31
  • 2010-12-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多