Считайте следующее: выдержки из приложения 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();
}
}
Поэтому, учитывая интерфейс Metro с двумя кнопками и обработчиками событий кликов, единственное отличие состоит в том, что второй обработчик событий помечен как async
.
Затем, щелкая по каждой кнопке, я ожидаю, что обработчик UnhandledException будет вызван в обоих случаях, так как они должны быть введены через поток пользовательского интерфейса и связанный с ним контекст синхронизации.
Мое понимание заключается в том, что для методов async void
любые исключения должны быть захвачены и "возвращены" (сохраняются исходные стекы) через исходный контекст синхронизации, что также четко указано в "Часто задаваемые вопросы по Async/Await" .
Но обработчик UnhandledException имеет не, вызванный в случае async
, поэтому приложение аварийно завершает работу! Поскольку это бросает вызов тому, что я считаю совершенно интуитивной моделью, мне нужно знать, почему! Да, я знаю, что я мог бы обернуть тело обработчика в try { } catch { }
, но мой вопрос в том, почему он не обратный обработчик UnhandledException?
Чтобы еще раз подчеркнуть, почему это не имеет смысла, рассмотрите следующие практически идентичные выдержки из приложения WPF, также используя async/wait и Targeting.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 Обработчик события UnhandledException выше.]
Затем, щелкая по каждой кнопке, обработчик DispatcherUnhandledException действительно вызывается в обоих случаях, как и ожидалось, и приложение вызывает не.