以下は、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();
}
}
したがって、2つのボタンとそのクリックイベントハンドラーを備えたMetro UIを考えると、唯一の違いは、2番目のイベントハンドラーがとしてマークされていることasync
です。
次に、各ボタンをクリックすると、どちらの場合もUnhandledExceptionハンドラーが呼び出されると思います。どちらも、UIスレッドと関連する同期コンテキストを介して入力する必要があるためです。私の理解では、async void
メソッドの場合、例外はすべてキャプチャされ、初期同期コンテキストを介して「再スロー」(元のスタックトレースを保持)する必要があります。これは、Async / AwaitFAQにも明確に記載されています。
ただし、この場合はUnhandledExceptionハンドラーが呼び出されないasync
ため、アプリケーションがクラッシュします。これは、他の点では非常に直感的なモデルと私が考えるものに挑戦するため、その理由を知る必要があります。はい、ハンドラーの本体をでラップできることは知ってtry { } catch { }
いますが、私の質問は、バックストップのUnhandledExceptionハンドラーが呼び出されないのはなぜですか?
これが意味をなさない理由をさらに強調するために、非同期/待機を使用し、.NETFramework4.5を対象とするWPFアプリからの次の実質的に同一の抽出を検討してください。
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にはApplicationDispatcherUnhandledExceptionイベントハンドラーとAppDomainUnhandledExceptionイベントハンドラーの両方があるという微妙な違いがありますが、Metro / WinRTApplicationUnhandledExceptionイベントハンドラーと連携するDispatcherUnhandledExceptionで例外を「handled」としてマークすることしかできません。その上。]
次に、各ボタンをクリックすると、予想どおり、どちらの場合もDispatcherUnhandledExceptionハンドラーが実際に呼び出され、アプリケーションはクラッシュしません。