同期コンテキスト、非同期、待機の学習

非同期プログラミングは、メインアプリケーションスレッドとは別にタスクを実行し、実行が終了したときにスレッドに通知できる並列プログラミングの形式です。非同期は、アプリケーションの実行フローや応答性を維持する必要がなく、タスクを実行するのに役立ちます。

マイクロソフトは、マルチコアシステムの利点を活用するために、.NetFrameworkでの並列プログラミングのサポートを提供しています。非同期を活用して、アプリケーションのパフォーマンスと応答性を向上させることができます。

基本的に、アプリケーションには2つのタイプの操作があります。これらには、コンピューティングバウンドおよびI / Oバウンド操作が含まれます。計算バインド操作は、メインスレッドが実行を続行できるように、別のスレッドで計算を実行できる操作です。逆に、I / Oバウンド操作は、外部で実行される操作であるため、I / Oの進行中に現在のスレッドをブロックする必要はありません。

同期コンテキストと実行コンテキスト

すべてのスレッドにはコンテキストが関連付けられており(これは「現在の」コンテキストとも呼ばれます)、これらのコンテキストはスレッド間で共有できます。ExecutionContextには、プログラムが実行されている現在の環境またはコンテキストの関連メタデータが含まれています。SynchronizationContextは抽象化を表し、アプリケーションのコードが実行される場所を示します。

SyntaxContextを使用すると、タスクを別のコンテキストにキューイングできます。すべてのスレッドが独自のSynchronizatonContextを持つことができることに注意してください。最近、SynchronizationContextクラスがSystem.Threading名前空間に追加され、スレッド間の通信が容易になりました。ここでSynchronizationContextとExecutionContextについて詳しく読むことができます。

AsyncとAwaitの詳細

3つの非同期プログラミングパターンには次のものがあります。

  1. 非同期プログラミングモデル(APM)
  2. イベントベースの非同期パターン(EAP)
  3. タスクベースの非同期パターン(TAP)

これらすべての中で最新の、推奨される、そして最もエレガントなのはTAPです。

void、Task、またはTaskを返す「async」キーワードを使用してメソッドをマークできることに注意してください。戻り値の型がTaskまたはTaskである非同期メソッド内で例外が発生した場合、例外の詳細はTaskインスタンス内に格納されることに注意してください。

逆に、戻り値の型がvoidの非同期メソッド内で例外が発生した場合、例外の詳細は、非同期メソッドが呼び出されたときにアクティブだったSynchronizationContext内に格納されます。本質的に、非同期メソッド内で記述された例外ハンドラーを使用して、戻り値の型がvoidである非同期メソッド内で発生した例外を処理することはできません。計算とエラー処理のセマンティクスが異なるため、使用する十分な理由がない限り、voidの戻り値の型を持つ非同期メソッドを避けることをお勧めします。

非同期メソッド内で「await」キーワードを使用すると、メソッドはステートマシン内で分割されます。 「await」キーワードは現在のSynchronizationContextをキャプチャし、「await」キーワードを使用して待機していたタスクが完了するとすぐに、ステートマシンが再開され、呼び出し元メソッドのコードの実行が再開されることに注意してください。これも継続として知られています。一時停止ポイントが発生したときに「await」キーワードを使用して待機していたコードの実行が完了している場合、非同期メソッド(「async」としてマークされているメソッド)は同期的に実行されます。待機中のコードの実行が完了していない場合、待機中のコードに継続デリゲートがアタッチされます。

voidを返す非同期メソッドを利用して、非同期イベントハンドラーを作成できます。 Mainメソッドは、アプリケーションのエントリポイントであるため、「async」キーワードでマークすることはできません。「async」Mainメソッドは、呼び出された瞬間に終了します。 「await」キーワードは、メソッドが一時停止および再開ポイントを持つことができることをコンパイラーに通知します。ちなみに、「await」キーワードは、「async」キーワードを使用して非同期としてマークされたメソッドでのみ使用できます。

非同期メソッドが呼び出されると、メソッドの戻り値の型に関係なく、現在のスレッドで同期的に実行されます。「async」キーワードを使用してメソッドを非同期としてマークすると、メソッドを複数のタスクに分割できることをコンパイラーに通知するだけです。これらのタスクの一部は非同期で実行される場合があります。また、メソッドに「async」キーワードを含めても、スレッドプールの一部としてメソッド呼び出しがキューに入れられることはありません。非同期性(つまり、メソッドが非同期動作をするかどうか)は、実際には、「await」キーワードを使用してメソッドで言及した一時停止ポイントに依存します。非同期メソッド内に「await」キーワードを含めない場合、メソッド全体が同期的に実行されます。