24

待機中のasyncメソッドが例外をスローすると、例外はどこかに格納され、スローが遅延します。WinFormsまたはWPFアプリケーションでSynchronizationContext.Currentは、例外のスローをポストするために使用します。ただし、たとえばコンソールアプリケーションでは、スレッドプールで例外がスローされ、アプリケーションがダウンします。

asyncメソッドからスローされた例外がアプリケーションを停止させないようにするにはどうすればよいですか?

編集:

どうやら私が説明している問題は、私がvoid asyncメソッドを持っているからです。コメントを参照してください。

4

2 に答える 2

21

非同期メソッドからスローされた例外がアプリケーションを停止させるのを防ぐにはどうすればよいですか?

次のベストプラクティスに従ってください。

  1. すべてのasyncメソッドは戻る必要があります。Taskまたは、返す必要Task<T>ない限り(イベントハンドラーなど)。void
  2. ある時点で、awaitすべてTaskのメソッドから返される必要がありasyncます。これを実行したくない唯一の理由は、操作の結果を気にしない場合(たとえば、操作をキャンセルした後)です。
  3. イベントハンドラから例外をキャッチする必要がある場合は、async voidイベントハンドラでキャッチします。これは、同期コードの場合とまったく同じです。

私のasync/awaitイントロの投稿が役立つかもしれません。ここでは、他のいくつかのベストプラクティスについても説明します。

于 2012-09-07T11:41:24.373 に答える
13

メソッドが開始されるasyncと、現在の同期コンテキストがキャプチャされます。この問題を解決する方法は、例外をキャプチャする独自の同期コンテキストを作成することです。

ここでのポイントは、同期コンテキストがコールバックをスレッドプールにポストすることですが、その周りにtry/catchがあります。

public class AsyncSynchronizationContext : SynchronizationContext
{
    public override void Send(SendOrPostCallback d, object state)
    {
        try
        {
            d(state);
        }
        catch (Exception ex)
        {
            // Put your exception handling logic here.

            Console.WriteLine(ex.Message);
        }
    }

    public override void Post(SendOrPostCallback d, object state)
    {
        try
        {
            d(state);
        }
        catch (Exception ex)
        {
            // Put your exception handling logic here.

            Console.WriteLine(ex.Message);
        }
    }
}

上記ではcatch、例外処理ロジックを配置できます。

次に、このメカニズムでメソッドを実行するすべてのスレッド(SynchronizationContext.Currentis )で、現在の同期コンテキストを設定する必要があります。[ThreadStatic]async

SynchronizationContext.SetSynchronizationContext(new AsyncSynchronizationContext());

完全なMain例:

class Program
{
    static void Main(string[] args)
    {
        SynchronizationContext.SetSynchronizationContext(new AsyncSynchronizationContext());

        ExecuteAsyncMethod();

        Console.ReadKey();
    }

    private static async void ExecuteAsyncMethod()
    {
        await AsyncMethod();
    }

    private static async Task AsyncMethod()
    {
        throw new Exception("Exception from async");
    }
}
于 2012-09-07T08:25:53.387 に答える