async + await == sync?


24

非同期Web要求の作成について説明しているこの投稿を見つけました。

さて、単純さはさておき、現実の世界であなたがすることは非同期リクエストを作成して次の行でそれを待つことだけです、そもそも同期呼び出しをするのと同じではないでしょうか?


5
ではない正確に。結果が得られるまで何も起こらないという意味で、コードは同期的です。ただし、その下では、おそらく非同期メソッドが返されるまで実行していたスレッドを放棄し、実行を継続するために別のスレッドが割り当てられました。
R0MANARMY

2
それはありますが、非同期では別の非同期を同時に行い、2を待つことができます。同期では不可能です
ラチェットフリーク

C#での非同期の裏側のいくつかについて説明している記事(tomasp.net/blog/async-compilation-internals.aspx)は、C#およびF#での非同期プログラミングをカバーするシリーズの一部です。
ポール

@ratchetfreak:はい、それは言うまでもありませんが、複数の通話を行っている場合。
Mrchief

@ R0MANARMY:アプリが他のことをしている場合、yesおよびasync + awaitが有効にします。アキムは最高だと言っています!ただし、コードがbutton_clickハンドラー、またはそのようなイベントハンドラーにないことを想像してください。誰かが盲目的にコード(async + await行)を任意のメソッドにコピーすると、コードは非同期であるが実際にはそうではないという印象を与える可能性があります。
-Mrchief

回答:


32

いいえ、継続のasync + await != syncため

MSDNの「AsyncとAwaitを使用した非同期プログラミング(C#とVisual Basic)」

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

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

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

非常にうまく言った!
-Mrchief

もっと詳しく説明してください。これがないと... UIを操作できなくなります...これはメインスレッド上にあるためです。つまり、これは、対話がWebサーバースレッドとは別のWebに並置されたアプリケーションタイプのプログラムでのみ適用可能になるということです。したがって、ナットシェルでは、これは重要になります。つまり、メインスレッドが実行中のスレッドである場合、sync *ではありません。これにより、App(1メインスレッド)で2つのボタンがクリックされるなど、予期しない動作が発生しませんか?
Seabizkit 16

どうConsole.WriteLine(await GetStringOverNetwork());?非同期呼び出しの出力が必要な場合はどうなりますか?スレッドが実行を継続できる可能性がある場合でも、プログラムは最初のアクセスでブロックしますか?
アンドリュー

6

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

あなたasyncのためのコードブロックが待機しているawait通話が継続して返すために、しかし、あなたのアプリケーションの残りの部分は待っていないと、まだ通常のように続けることができます。

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


同期呼び出しをasync + awaitとして実装できませんでしたか?
ラチェットフリーク

@ratchetfreak await / asyncのセットアップにはオーバーヘッドがあると思うので、アプリケーション全体をコーディングする必要はないと思います。長時間実行される可能性のあるコードブロックを実行するためにのみ使用するので、アプリケーションがロックされることはありません。:)
レイチェル

5

async / awaitに関して明確にすることを許可してください。

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

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

基礎となるステートマシンは、非同期/待機の使用の背後にある「魔法」の一部であり、使用されたり見逃されたりすることはありません。


2

私は同じ質問を念頭に置いてこれを見つけましたが、回答を読んだ後、質問は「フードの下の魔法」への参照と混同して長引くようです。

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

  • asyncキーワードは、あなたが使用することを可能にする非同期メソッド、メソッドになりawait、その本体にキーワードを。
  • 場合はawaitキーワードが適用され、それが呼び出すメソッドを中断し、待望のタスクが完了するまで、収量は呼び出し元に戻って制御します。
  • awaitasyncメソッド内でのみ使用できます。

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

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

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

  • それはあなたのアプリケーションがどのように書かれているかによりますawait同じコンテキストで順番に起動される一連の依存edタスクの場合(「非同期/待機の動作を理解しようとする」を参照)

    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現在のコンテキストが呼び出される場所から外部コンテキストに実行をもたらします。ただし、外側のコンテキスト自体が現在のコンテキストを待機している場合はawait、同じコンテキストのシーケンシャルsに似ています。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.