23

私は c# の新しい await/async キーワードに慣れようとしていますが、よく理解できない側面がいくつか見つかりました。

  1. 競合状態から始めましょう:

    Stream s=...
    ...
    for(int i=0;i<100;i++)
    {
        s.WriteAsync(new byte[]{i},0,1);
    }
    

    これは常に期待どおりに機能しますか (たとえば、13254 などではなく、ファイル 12345..... に書き込みます)?

    2 つ目は、await 演算子が含まれていない場合、非同期関数が同期的に実行されることです。また、マイクロソフトのドキュメントによると、非同期関数は常に呼び出し元スレッドで実行されます (BeginInvoke と比較して)。これにより、次の 3 つの質問が表示されます。

  2. 呼び出し元の関数にリリースされる前に、非同期関数はどの程度実行されますか?

    async void MyAsyncFunction()
    {
        Operation1();
        Operation2();
        Operation3();
        ....
        Stream s=...;
        await s.WriteAsync(....);
    }
    

    私が読んだ await/async に関する記事では、await 演算子を使用しない非同期関数は順次実行され、async/await を使用するとすぐに戻ると書かれていました。MyAsyncFunctionしかし、いつでも Operation1...Operation3 を実行してから、ヒットしたときにリリースすることができるのは私にはしつこいですawait s.WriteAsync

  3. Thread.Sleep次のように非同期関数で使用するとどうなりますか。

    async void DoStuff()
    {
        Stream s=...;
        ...
        await s.WriteAsync(....);
        Thread.Sleep(10000);
        ....
    }
    

    Thread.Sleep は、それが実行されるスレッド全体をブロックしますか、それとも非同期関数だけをブロックしますか?

  4. 非同期関数の 1 つで使用semaphore.Wait()し、セマフォが他の非同期関数によって解放されることを期待するとどうなりますか。これはスレッドの場合と同じように動作しますか、それともデッドロックを引き起こしますか?

  5. await非同期関数の外では機能しません。なんで?

4

3 に答える 3

16

私のasyncイントロを読むことをお勧めします。

これは常に期待どおりに機能しますか (たとえば、13254 などではなく、ファイル 12345..... に書き込みます)?

awaitいいえ。 への呼び出しが必要ですWriteAsync

呼び出し元の関数にリリースされる前に、非同期関数はどの程度実行されますか?

awaitまだ完了していない操作になるまで。

Thread.Sleep は、それが実行されるスレッド全体をブロックしますか、それとも非同期関数だけをブロックしますか?

Thread.Sleep- および他のすべてのブロッキング メソッド -asyncメソッドとそれを実行しているスレッドをブロックします。

原則として、メソッド内でブロッキング メソッドを使用しないasyncでください。

非同期関数の 1 つで semaphore.Wait() を使用すると、セマフォが他の非同期関数によって解放されることが期待されます。これはスレッドの場合と同じように動作しますか、それともデッドロックを引き起こしますか?

それはあなたの文脈に完全に依存します。Waitはブロッキング メソッドであるため、「他の」asyncメソッドがブロックされたメソッドによって保持されているコンテキストを必要とする場合、デッドロックが発生します。

フレンドリーであることに注意してSemaphoreSlimくださいasyncWaitAsyncの代わりに使用できますWait

await は非同期関数の外では機能しません。なんで?

asyncキーワードがキーワードを有効にするためawaitです。これは、C# 言語に対する新しいキーワードの影響を最小限に抑え、コードを読みやすくするために行われました。

于 2012-11-17T14:03:54.863 に答える
15

awaitオペレーターに関する質問に対する回答は、Eric Lippert による次の投稿で見つけることができます。

「await」演算子は…「このメソッドは、非同期操作が戻るまで現在のスレッドをブロックする」という意味ではありません。それは、非同期操作を同期操作に戻すことになります。これは、まさに私たちが避けようとしているものです。むしろ、それはその反対を意味します。これは、「待っているタスクがまだ完了していない場合は、このメソッドの残りの部分をそのタスクの継続としてサインアップし、すぐに呼び出し元に戻る」という意味です。タスクは、完了時に継続を呼び出します。-- エリック・リッパート

于 2012-11-17T10:38:40.117 に答える
0

要するに、答えは「非常に」のようです。以下はすべての質問に答えているわけではありませんが、一般的な十分なユースケースに当てはまると思います. 彼らが参照しているネットワーク IO ではなく、ストリームを考えてください。

オーバーラップしたネットワーク IO の場合、IO 完了ポートが使用され、ハードウェア割り込みによってコールバックがトリガーされます。

これは、完了を「待っている」間、スレッドが消費されないことを意味します。[...]

1つのスレッドですべてを実行できます。[...] ただし、プラットフォーム、「awaiter」の実装、および使用されている同期コンテキストによって異なります。

http://social.msdn.microsoft.com/Forums/en-US/async/thread/a46c8a54-f8d4-4fa9-8746-64d6a3a7540d/

于 2012-11-17T09:36:13.280 に答える