web-dev-qa-db-ja.com

async + await == sync?

これに遭遇しました post 非同期Webリクエストの作成について説明しています。

単純化はさておき、現実の世界では、非同期要求を作成して次の行でそれを待つだけの場合、最初に同期呼び出しを行うのと同じではありませんか?

25
Mrchief

番号、 async + await != sync継続のため

MSDNから '非同期および待機による非同期プログラミング(C#およびVisual Basic)'

非同期メソッドは、非ブロッキング操作を目的としています。 asyncメソッドのawait式は、待機中のタスクの実行中に現在のスレッドをブロックしません。代わりに、式は継続としてメソッドの残りの部分を登録し、非同期メソッドの呼び出し元に制御を返します。

たとえば、非同期実行はUIスレッドをブロックせず、Some TextBox.Textはダウンロードが完了した後に更新されます

private async void OnButtonClick()
{
   SomeTextBox.Text = await new WebClient().DownloadStringTaskAsync("http://stackoverflow.com/");
}
34
Akim

いいえ、同じではありません。

asyncコードブロックはawait呼び出しが戻るのを待機していますが、アプリケーションの残りの部分は待機していないため、通常どおり続行できます。

対照的に、同期呼び出しでは、コードが実行を完了するまでアプリケーションまたはスレッド全体を待機させ、他の処理を続行します。

6
Rachel

Async/awaitに関して明確にさせてください。

Awaitが発生すると、基になるステートマシンにより、制御がすぐに返されます。次に、待機中の呼び出しが完了すると、基礎となる状態マシンにより、待機中の呼び出しの後の行から実行を再開できます。

したがって、非同期ブロックはブロックされず、待機中の呼び出しが完了するのを待機しません。制御は、awaitコマンドが検出されるとすぐに返されます。

基礎となる状態マシンは、使用されず見逃されない非同期/待機の使用の背後にある「魔法」の一部です。

5
Cedric Harris

私は同じ質問を念頭に置いてこれにつまずきましたが、回答を読んだ後、質問は「フードの下の魔法」への言及に混同されたようです。

上記の 非同期プログラミング から:

  • asyncキーワードは、メソッドを非同期メソッドに変換します。これにより、本文でawaitキーワードを使用できます。
  • awaitキーワードが適用されると、呼び出し元のメソッドが中断され、待機中のタスクが完了するまで、呼び出し元に制御が戻ります。
  • awaitは、asyncメソッド内でのみ使用できます。

awaitを検出したコンテキストはブロックされますか?

  • はい。これは基本的に、実行のコンテキストで既知の状態を維持するためのローカル同期バリアです。ただし、他のコンテキストがある場合は結合されません。

残りのアプリケーションブロックをawaitで実行しますか?

  • それは、アプリケーションの記述方法に依存します。同じコンテキストで順次起動される一連の依存するawaitedタスクの場合(参照: 非同期/待機の動作を理解しようとしています

    await asyncCall1();
    await asyncCall2();  // waits for asyncCall1() to complete
    

    このようにして、各awaitは次のもののスポーンをブロックします。

    一方、並行して起動された同じ依存タスクは並行して実行され、コンテキストは応答時にのみブロックされます。 await

    Task<int> t1 = asyncCall1();
    Task<string> t2 = asyncCall2();  // runs in parallel with asyncCall1()
    int val = await t1;
    string str = await t2;  // waits for asyncCall1() to complete
    

    一般に、awaitは、現在のコンテキストが呼び出される外部コンテキストに実行を渡します。ただし、外部コンテキスト自体が現在を待機している場合、それは同じコンテキスト内のシーケンシャルawaitsのようなものです。

したがって、asyncのメリットを享受するには、複数の並列コンテキスト(UI、データクライアントなど)を実行するようにアプリケーションを設計する必要があります。次に、1つのコンテキストのawaitが他のコンテキストに実行をもたらすため、アプリケーション全体が個別にブロックされません。 await

2
oversynched