13

以下は、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ハンドラーが実際に呼び出され、アプリケーションはクラッシュしません。

4

6 に答える 6

5

ここで回答:非同期イベント コールバックから発生した UnhandledException はありません

これは、WinRT の既知の制限です。うまくいけば、次のアップデートで修正されるでしょう。

于 2012-10-08T16:15:14.057 に答える
5

次の投稿の解決策は私にとってはうまくいきましたが、小さな変更が 1 つあります。App.OnLaunched イベントに

http://www.markermetro.com/2013/01/technical/handling-unhandled-exceptions-with-asyncawait-on-windows-8-and-windows-phone-8/

于 2013-09-05T02:33:24.053 に答える
4

As explained in the documentation (source: http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.application.unhandledexception.aspx):

It’s important to be aware of several limitations of the Application.UnhandledException event. This event is only used with exceptions encountered by the XAML framework. Exceptions encountered by other Windows Runtime components or parts of the application that are not connected to the XAML framework will not result in this event being raised.

For example, if a different Windows component calls into application code and an exception is thrown and not caught, the UnhandledException event won’t be raised. If the application creates a worker thread, and then raises an exception on the worker thread, the UnhandledException event won’t be raised.

As pointed out in this conversation, only way to retrieve exceptions happening in a worker thread is to wrap them in a try/catch block. As a consequence, here's the workaround I'm using in my app: instead of using Task.Run or equivalents to execute code on a worker thread from the UI, I'm using this method:

/// <summary>
/// Runs code in a worker thread and retrieves a related exception if any.
/// </summary>
/// <param name="target">The target.</param>
/// <param name="action">The action.</param>
public static void SafeRun(this DependencyObject target, Action action)
{
    Task task = ThreadPool.RunAsync(o =>
    {
        try
        {
            action();
        }
        catch (Exception ex)
        {
            /* Call the same error logging logic as in the UnhandledException event handler here. */
        }
    }).AsTask();
    task.Wait();
}

Bottom line is that to log all errors in your app, you should:

  1. Subscribre to the UnhandledException event to get XAML stack related errors,
  2. Wrap actions happening in a worker threads in a try/catch block.
于 2012-12-07T08:56:29.987 に答える
-1

TaskScheduler の UnobservedTaskException イベントを試す

于 2012-10-20T20:21:26.513 に答える