将以下内容视为从 Windows 8 Metro / WinRT 应用程序中提取的内容,这些内容已减少到显示异常所需的最低限度:
public class App : Application
{
public App()
{
UnhandledException += (sender, e) => e.Handled = true;
}
}
public class MainPage : Page
{
private void Button_Click_1(object sender, RoutedEventArgs e)
{
throw new NotSupportedException();
}
private async void Button_Click_2(object sender, RoutedEventArgs e)
{
throw new NotSupportedException();
}
}
因此,给定一个带有两个按钮及其 click 事件处理程序的 Metro UI,唯一的区别是第二个事件处理程序被标记为async
.
然后单击每个按钮,我希望在这两种情况下都会调用 UnhandledException 处理程序,因为它们(应该)都通过 UI 线程和关联的同步上下文输入。我的理解是,对于async void
方法,任何异常都应该被捕获并通过初始同步上下文“重新抛出”(保留原始堆栈跟踪),这在Async / Await FAQ中也有明确说明。
但是在这种情况下没有调用UnhandledException 处理程序async
,所以应用程序崩溃了!由于这挑战了我认为非常直观的模型,我需要知道为什么!是的,我知道我可以将处理程序的主体包装在 a 中try { } catch { }
,但我的问题是为什么不调用 backstop UnhandledException 处理程序?
为了进一步强调为什么这没有意义,请考虑以下来自 WPF 应用程序的几乎相同的摘录,也使用 async / await 并以 .NET Framework 4.5 为目标:
public class App : Application
{
public App()
{
DispatcherUnhandledException += (sender, e) => e.Handled = true;
}
}
public class MainWindow : Window
{
private void Button_Click_1(object sender, RoutedEventArgs e)
{
throw new NotSupportedException();
}
private async void Button_Click_2(object sender, RoutedEventArgs e)
{
throw new NotSupportedException();
}
}
[WPF既有Application DispatcherUnhandledException事件处理程序也有AppDomain UnhandledException事件处理程序的细微差别,但只能在DispatcherUnhandledException中将异常标记为“已处理”,这与Metro/WinRT Application UnhandledException事件处理程序一致以上。]
然后单击每个按钮,DispatcherUnhandledException 处理程序确实在两种情况下都被调用,正如预期的那样,应用程序不会崩溃。