【发布时间】: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