11

簡単な例を投稿しましょう。

    private void MyMethod()
    {
        Task task = MyAsyncMethod();
        task.Wait();
    }

    private async Task MyAsyncMethod()
    {
        //Code before await
        await MyOtherAsyncMethod();
        //Code after await
    }

上記のコードを、コンソール アプリのようなシングル スレッド アプリで実行するとします。コードを実行する方法を理解するのに苦労してい//Code after awaitます。 コントロールでキーワードを押すとに戻ること

を理解していますが、その後 でスレッドをロックしています。スレッドがロックされている場合、それを受け取るはずの スレッドがロックされている場合、どのように実行できますか? 実行するために新しいスレッドが作成されますか? それとも、メインスレッドが魔法のようにステップアウトして実行されますか? これがどのように機能するのかわかりませんか?awaitMyAsyncMethod()MyMethod()task.Wait()//Code after await

//Code after awaittask.Wait()//Code after await

4

2 に答える 2

15

.でメイン スレッドをブロックしているため、投稿されたコードがメイン スレッドから呼び出された場合、Winform アプリで「デッドロック」しますWait()

しかし、コンソールアプリではこれが機能します。しかし、どのように?

に答えが隠されていSynchronizationContext.Currentます。await「SynchronizationContext」をキャプチャし、タスクが完了すると、同じ「SynchronizationContext」で続行されます。

winformアプリでは、「メッセージループ」への呼び出しにポストするものをSynchronizationContext.Current設定しますが、誰がそれを処理するのでしょうか? WindowsFormsSynchronizationContextout メイン スレッドは で待機中Wait()です。

コンソール アプリSynchronizationContext.Currentではデフォルトで設定されないnullため、await でキャプチャできる「SynchronizationContext」がない場合に、継続をThreadPool(TaskScheduler.Default である ThreadpoolTask​​Scheduler) にスケジュールし、await の後のコードが (スレッドプール スレッドを介して) 動作するようになります。 .

前述のキャプチャ動作はTask.ConfigureAwait(false);、winform アプリのデッドロックを防ぐために使用できますが、コードawaitは UI スレッドで実行されなくなります。

于 2013-10-23T13:56:57.220 に答える
14

待機後に //Code を実行するために新しいスレッドが作成されますか?

多分。そうでないかもしれない。の awaitable パターン実装は、await 式の開始時に「現在」だった同期コンテキストを使用してTask、継続 (式の後のビット) を実行します。awaitたとえば、UI スレッドのコンテキストにいる場合、同じ UI スレッドに戻ることになります。スレッド プール スレッドにいる場合は、スレッド プール スレッドに戻ることになりますが、それは別のスレッドである可能性があります。

もちろん、コード サンプルでは、​​UI スレッドにいる場合、への呼び出しによってWait()UI スレッドがブロックされるため、継続を実行できません。これについては注意が必要です。(完了するかどうかわからず、現在のスレッドでの作業が必要になる可能性のあるタスクに対してWait()またはを呼び出すことは、悪い考えです。)Result

同じコンテキストで続行する必要がないTask.ConfigureAwaitという意図を表現できるように呼び出すことができることに注意してください。これは通常、実行するスレッドを気にしないライブラリ メソッドに適しています。

await task.ConfigureAwait(false);

(それはスレッド以上に影響します - キャプチャされるかどうかはコンテキスト全体です。)

await の内部で何が行われているのかを理解することは良い考えだと思います。オンラインにはたくさんのドキュメントがあります。簡単なプラグインを許可していただければ、C# in Depth の第 3 版と、このトピックに関する Tekpub スクリーンキャスト シリーズもあります。または、MSDNから始めて、そこから進みます。

于 2013-10-23T13:47:06.907 に答える