6

私は、C# 5 の非同期性に関する Eric Lippert のブログ記事を読んでおり (パート 4が特に関連しています)、Anders PDC10 がこの件について話しているのを見てきましたが、シングル スレッド コンテキストで非同期メソッドからの継続がどのように再開されるかについては不明です。

どちらの情報源も、単一のスレッド化された UI ループで非同期メソッドを使用して応答性を向上させることについて議論しており、Anders の例では、非同期タスクが完了すると、メッセージ ポンプにメッセージを追加することによって継続がスケジュールされると述べています。

非同期メソッドは、コンテキスト固有のアクションのように見えるものを実行する必要があることを本当に認識していますか?それとも単純化されたものですか?

より一般的には、単一のスレッド化されたコンテキストで非同期メソッドからの再開をどのように処理できるでしょうか? 単一のスレッド内でスケジューリングする必要はありますか?

4

2 に答える 2

7

もちろん、ジョンの答えは素晴らしいです。もう1つ追加するだけだと思いました。

ボタンをクリックするとコードを実行するフォーム上にボタンが 1 つある WinForms アプリケーションを考えてみましょう。

ボタンをクリックしないとどうなりますか? 何もない。プロセスは存在し、コードは実行されていますが、何もしていないようです。実際には、UI スレッドでメッセージを処理し、興味深いものはないと判断していますが、興味深いことをしているようには見えません。

ボタンをクリックすると、突然、これらのメッセージの 1 つが興味深いものになり、メッセージ ポンプは、そのクリック イベントを確認すると、何らかのコードを実行する必要があることを認識します。そうです。

シングル スレッドでの非同期のシナリオもまったく同じです。継続 -- 「タスクが終了した後に何をすべきか」コードは、事実上、「タスクが終了した」イベントの「イベント ハンドラー」です。タスクが終了すると、「ボタンを押して」、UI スレッドのメッセージ キューにメッセージをエンキューします。それが UI スレッドからなのか、I/O 完了スレッドなどからなのかは問題ではありません。UI スレッドがそのメッセージの処理に取りかかると、継続が呼び出されます。UI スレッドがボタンのクリックを処理するときと同じように、クリック ハンドラーを呼び出します。

于 2011-03-21T15:20:56.413 に答える
7

タスクの継続は、継続をスケジュールする必要がある場所を認識しています。たとえば、「任意のスレッド プール スレッド」または「UI スレッド」です。

ただし、この動作は "awaiter" によって決定されます。実際には、C# コンパイラが担当することの一部ではありません。コンパイラBeginAwaitは継続を呼び出して渡すだけです。awaiter は、タスクが既に同期的に完了しているかどうか、または呼び出し元が戻り、継続を非同期的に発生させる必要があるかどうかを示すブール値を返します。

現時点では、その決定は awaiter によって返される- で行われますが、最終的TaskExにすべてがバンドルされるのを見て驚くことはありません。Taskそれは、その後のアクションをどのように処理する必要があるかを知っている同期コンテキストのようなものを流すことができます。

あなたが検討している真のシングルスレッドのコンテキストの種類がよくわかりません...または、作業の大部分を単一のスレッドで実行する必要がある状況を考えていますが、他のスレッドが関与する可能性があります非同期ビット (たとえば、HTTP パケットが受信され、IO 完了ポート スレッドで処理され、応答がUI スレッドで処理されたとき) ?

于 2011-03-21T12:30:31.827 に答える