「asyncvoid」(待機なし)と「void」の違いは何ですか

coder958452

StephenClearyによるasyncawaitに関する記事からの抜粋:

図2AsyncVoidメソッドの例外をキャッチでキャッチできない

private async void ThrowExceptionAsync()
{
  throw new InvalidOperationException();
}
public void AsyncVoidExceptions_CannotBeCaughtByCatch()
{
  try
  {
    ThrowExceptionAsync();
  }
  catch (Exception)
  {
    // The exception is never caught here!
    throw;
  }
}

... async voidメソッドからスローされた例外は、asyncvoidメソッドの開始時にアクティブだったSynchronizationContextで直接発生します...

それは実際にはどういう意味ですか?より多くの情報を収集するために、拡張例を作成しました。図2と同じ動作です。

static void Main()
{

    AppDomain.CurrentDomain.UnhandledException += (sender, ex) => 
    {
        LogCurrentSynchronizationContext("AppDomain.CurrentDomain.UnhandledException");
        LogException("AppDomain.CurrentDomain.UnhandledException", ex.ExceptionObject as Exception);
    };

    try
    {
        try
        {
            void ThrowExceptionVoid() => throw new Exception("ThrowExceptionVoid");

            ThrowExceptionVoid();
        }
        catch (Exception ex)
        {
            LogException("AsyncMain - Catch - ThrowExceptionVoid", ex);
        }

        try
        {
            // CS1998 C# This async method lacks 'await' operators and will run synchronously. 
            async void ThrowExceptionAsyncVoid() => throw new Exception("ThrowExceptionAsyncVoid");

            ThrowExceptionAsyncVoid();
        }
        // exception cannot be caught, despite the code running synchronously.
        catch (Exception ex) 
        {
            LogException("AsyncMain - Catch - ThrowExceptionAsyncVoid", ex);
        }
    }
    catch (Exception ex)
    {
        LogException("Main", ex);
    }

    Console.ReadKey();
}

private static void LogCurrentSynchronizationContext(string prefix)
    => Debug.WriteLine($"{prefix} - " +
        $"CurrentSynchronizationContext: {SynchronizationContext.Current?.GetType().Name} " +
        $"- {SynchronizationContext.Current?.GetHashCode()}");

private static void LogException(string prefix, Exception ex)
    => Debug.WriteLine($"{prefix} - Exception - {ex.Message}");

デバッグ出力:

Exception thrown: 'System.Exception' in ConsoleApp3.dll
AsyncMain - Catch - ThrowExceptionVoid - Exception - ThrowExceptionVoid
Exception thrown: 'System.Exception' in ConsoleApp3.dll
An exception of type 'System.Exception' occurred in ConsoleApp3.dll but was not handled in user code
ThrowExceptionAsyncVoid
AppDomain.CurrentDomain.UnhandledException - CurrentSynchronizationContext:  - 
AppDomain.CurrentDomain.UnhandledException - Exception - ThrowExceptionAsyncVoid
The thread 0x1c70 has exited with code 0 (0x0).
An unhandled exception of type 'System.Exception' occurred in System.Private.CoreLib.ni.dll
ThrowExceptionAsyncVoid
The program '[18584] dotnet.exe' has exited with code 0 (0x0).

詳細が欲しい

  • (私の例のように)現在の同期コンテキストがない場合、例外はどこで発生しますか?
  • async void(なしawait)との違いは何ですかvoid
    • コンパイラは警告します CS1998 C# This async method lacks 'await' operators and will run synchronously.
    • なしawait同期して実行される場合、なぜ単純なものとは異なる動作をするのvoidですか?
    • async Taskていないとawaitも異なる振る舞いTask
  • 間のコンパイラ動作の違いは何ですかasync voidとはasync Taskここで提案さTaskasync voidているようにオブジェクトは実際に内部で作成されていますか?

編集します。明確にするために、これはベストプラクティスに関する質問ではなく、コンパイラ/ランタイムの実装に関する質問です。

スティーブン・クリアリー

(私の例のように)現在の同期コンテキストがない場合、例外はどこで発生しますか?

慣例により、がの場合、それSynchronizationContext.Currentnull実際SynchronizationContext.Currentにはのインスタンスと同じですnew SynchronizationContext()つまり、「同期コンテキストなし」は「スレッドプール同期コンテキスト」と同じです。

したがって、表示されている動作は、asyncステートマシンが例外をキャッチし、スレッドプールスレッドで直接発生させていることcatchです。このスレッドでは、例外をキャッチできません

この動作は奇妙に思えますが、次のように考えてくださいasync void。イベントハンドラーを対象としています。したがって、イベントを発生させるUIアプリケーションについて考えてみます。同期している場合、例外はUIメッセージ処理ループに伝播されます。このasync void動作は、次のことを模倣することを目的としています。例外(後の例外を含むawait)は、UIメッセージ処理ループで再発生します。これと同じロジックがスレッドプールコンテキストに適用されます。たとえば、同期System.Threading.Timerコールバックハンドラーからの例外はスレッドプールで直接発生し、非同期System.Threading.Timerコールバックハンドラーからの例外も発生します

待機せずに同期して実行される場合、単にvoidとは異なる動作をするのはなぜですか?

asyncステートマシンは、特別な例外を処理しています。

待機のない非同期タスクもタスクとは異なる動作をしますか?

絶対に。async Task非常によく似たステートマシンがあります-コードからの例外をキャッチし、返されたに配置しTaskます。これは、elidingにおける落とし穴の1 async/をawait非自明なコードのために

asyncvoidとasyncTaskのコンパイラの動作の違いは何ですか。

コンパイラーの場合、違いは例外の処理方法だけです。

これについて考える適切な方法は、それasync Taskが自然で適切な言語開発であるということです。async voidこれは、C#/ VBチームが採用した奇妙なハックであり、下位互換性の大きな問題なしに非同期イベントを有効にします。F#、Python、JavaScriptなどの他のasync/await対応言語にはasync void...の概念がないため、すべての落とし穴を回避できます。

ここで提案されているように、Taskオブジェクトは実際に非同期voidの内部で作成されていますか?

番号。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

待機していないTask.RunとTask.RunSynchronouslyの違いは何ですか

分類Dev

Selenium WebDriverの暗黙の待機と明示的な待機の違いは何ですか?

分類Dev

待機/通知と待機/割り込みの違いは何ですか?

分類Dev

Voidとパラメーターなしの違いは何ですか?

分類Dev

`inline`と` template <class = void> `の実際的な違いは何ですか?

分類Dev

タスクの開始と待機の違いは何ですか?

分類Dev

hp-ux ps、スリープと待機の違いは何ですか?

分類Dev

非同期/待機に関して、通常のforeach演算子とForEachLINQ演算子の違いは何ですか

分類Dev

java.lang.Voidとvoidの違いは何ですか?

分類Dev

待機ありとなしの返品に違いはありますか

分類Dev

typescriptのneverとvoidの違いは何ですか?

分類Dev

typescriptのneverとvoidの違いは何ですか?

分類Dev

使用と使用待機の違いは何ですか?そして、どの方法を使用するかをどのように決定できますか?

分類Dev

戻る&としないの違いは何ですか?

分類Dev

Pythonのパスとなしの違いは何ですか

分類Dev

Pythonの[なし]と[]の違いは何ですか?

分類Dev

これはasyncvoidの正しい使用法ですか?Xamarin

分類Dev

Kotlinコルーチンの起動/参加と非同期/待機の違いは何ですか

分類Dev

(void *)と(void(*)(argument type))キャストの違いは何ですか?

分類Dev

void関数(stuct * s)とvoid関数(stuct s)の違いは何ですか?

分類Dev

public voidメソッドとvoidメソッドの違いは何ですか?

分類Dev

ContinueWithとなしの違いは何ですか?

分類Dev

remove_referenceとそれなしの違いは何ですか

分類Dev

機能を使用する場合と使用しない場合の違いは何ですか?

分類Dev

Github WikiとReadmeの主な機能の違いは何ですか?

分類Dev

ブラウザの「設定」と「必要な機能」の違いは何ですか?

分類Dev

機能要件と非機能要件の違いは何ですか?

分類Dev

nullではないことと<> ''の違いは何ですか

分類Dev

機能の点でAVPlayerとAVAudioPlayerの違いは何ですか?

Related 関連記事

  1. 1

    待機していないTask.RunとTask.RunSynchronouslyの違いは何ですか

  2. 2

    Selenium WebDriverの暗黙の待機と明示的な待機の違いは何ですか?

  3. 3

    待機/通知と待機/割り込みの違いは何ですか?

  4. 4

    Voidとパラメーターなしの違いは何ですか?

  5. 5

    `inline`と` template <class = void> `の実際的な違いは何ですか?

  6. 6

    タスクの開始と待機の違いは何ですか?

  7. 7

    hp-ux ps、スリープと待機の違いは何ですか?

  8. 8

    非同期/待機に関して、通常のforeach演算子とForEachLINQ演算子の違いは何ですか

  9. 9

    java.lang.Voidとvoidの違いは何ですか?

  10. 10

    待機ありとなしの返品に違いはありますか

  11. 11

    typescriptのneverとvoidの違いは何ですか?

  12. 12

    typescriptのneverとvoidの違いは何ですか?

  13. 13

    使用と使用待機の違いは何ですか?そして、どの方法を使用するかをどのように決定できますか?

  14. 14

    戻る&としないの違いは何ですか?

  15. 15

    Pythonのパスとなしの違いは何ですか

  16. 16

    Pythonの[なし]と[]の違いは何ですか?

  17. 17

    これはasyncvoidの正しい使用法ですか?Xamarin

  18. 18

    Kotlinコルーチンの起動/参加と非同期/待機の違いは何ですか

  19. 19

    (void *)と(void(*)(argument type))キャストの違いは何ですか?

  20. 20

    void関数(stuct * s)とvoid関数(stuct s)の違いは何ですか?

  21. 21

    public voidメソッドとvoidメソッドの違いは何ですか?

  22. 22

    ContinueWithとなしの違いは何ですか?

  23. 23

    remove_referenceとそれなしの違いは何ですか

  24. 24

    機能を使用する場合と使用しない場合の違いは何ですか?

  25. 25

    Github WikiとReadmeの主な機能の違いは何ですか?

  26. 26

    ブラウザの「設定」と「必要な機能」の違いは何ですか?

  27. 27

    機能要件と非機能要件の違いは何ですか?

  28. 28

    nullではないことと<> ''の違いは何ですか

  29. 29

    機能の点でAVPlayerとAVAudioPlayerの違いは何ですか?

ホットタグ

アーカイブ