1. ホーム
  2. c#

[解決済み】非同期voidメソッドが投げる例外をキャッチする

2022-03-27 04:03:56

質問

Microsoft for .NETのasync CTPを使用しています。 非同期メソッドが投げる例外を呼び出し側メソッドでキャッチすることは可能ですか?

public async void Foo()
{
    var x = await DoSomethingAsync();

    /* Handle the result, but sometimes an exception might be thrown.
       For example, DoSomethingAsync gets data from the network
       and the data is invalid... a ProtocolException might be thrown. */
}

public void DoFoo()
{
    try
    {
        Foo();
    }
    catch (ProtocolException ex)
    {
          /* The exception will never be caught.
             Instead when in debug mode, VS2010 will warn and continue.
             The deployed the app will simply crash. */
    }
}

つまり、基本的には、非同期コードからの例外を呼び出し側のコードにバブルアップさせたいのです。 は、それが可能であるならば。

どのように解決するのですか?

読むとちょっと変な感じですが、そうです、例外は呼び出し側のコードにバブルアップされます。 もし await または Wait() を呼び出すと Foo .

public async Task Foo()
{
    var x = await DoSomethingAsync();
}

public async void DoFoo()
{
    try
    {
        await Foo();
    }
    catch (ProtocolException ex)
    {
          // The exception will be caught because you've awaited
          // the call in an async method.
    }
}

//or//

public void DoFoo()
{
    try
    {
        Foo().Wait();
    }
    catch (ProtocolException ex)
    {
          /* The exception will be caught because you've
             waited for the completion of the call. */
    }
} 

Stephen Clearyは、次のように書いています。 Async/Await - 非同期プログラミングのベストプラクティス :

非同期 void メソッドには、異なるエラー処理セマンティクスがあります。非同期タスクまたは非同期タスクメソッドから例外がスローされると、その例外は捕捉されてタスクオブジェクトに配置されます。非同期 void メソッドでは、Task オブジェクトは存在しないので、非同期 void メソッドからスローされる例外は、非同期 void メソッドの開始時にアクティブだった SynchronizationContext で直接発生します。

を使用することに注意してください。 Wait() は、.NETがメソッドの同期実行を決定した場合、アプリケーションをブロックする原因になることがあります。

この説明 http://www.interact-sw.co.uk/iangblog/2010/11/01/csharp5-async-exceptions このマジックは、コンパイラがどのような手順で実現するのかを説明しています。