待機中のasync
メソッドが例外をスローすると、例外はどこかに格納され、スローが遅延します。 WinFormsまたはWPFアプリケーションでは、SynchronizationContext.Current
を使用して例外のスローをポストします。ただし、たとえばコンソールアプリケーションの場合、スレッドプールで例外がスローされ、アプリケーションが停止します。
async
メソッドからスローされた例外がアプリケーションを停止させないようにするにはどうすればよいですか?
編集:
どうやら私が説明している問題は、私がvoid
async
メソッドを持っているためです。コメントを参照してください。
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.Current
は[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");
}
}
非同期メソッドからスローされた例外がアプリケーションをダウンさせるのを防ぐにはどうすればよいですか?
次のベストプラクティスに従ってください。
async
メソッドは、haveがTask
を返す場合を除いて、void
またはTask<T>
を返す必要があります(イベントハンドラーなど)。await
メソッドから返されたすべてのTask
sをasync
する必要があります。これを実行したくない唯一の理由は、操作の結果を気にしなくなった場合(たとえば、操作をキャンセルした後)です。async void
イベントハンドラーから例外をキャッチする必要がある場合は、イベントハンドラーでキャッチします。これが同期コードの場合とまったく同じです。私の async
/await
intro post 役立つと思うかもしれません。他のいくつかのベストプラクティスについても説明します。