.Netcore非同期プログラミング_どうやって?Net Coreでの非同期および待機の使用


.Netcore非同期プログラミング
非同期プログラミングでは、各文や命令をブロックしないプログラムを作成できます.これは、コンピュータが前のタスクが完了するまで他のタスクを実行し続けることを意味します.その結果、非同期プログラミングにより、より伸縮性と応答性の高いアプリケーションを構築できます.
asyncとawaitキーワードでは、非同期コードを記述できます.これらはすでにあります.Net Coreでは、使いやすさとパフォーマンスをシンプル化するために最適化されています.本文は討論した.Net Coreアプリケーションで非同期プログラミングを行う際に注意すべき点.
[Microsoft.Net 5は.Net Frameworkと.Net Coreを結合する:.Net Standardと.Net Coreの統合が開発者にとって何を意味するかを特定する.|InfoWorldのMicrosoft Architectブログから.Net Frameworkと.Net Coreの活用方法を理解する.|InfoWorldのApp Dev Reportニュース通信を通じてプログラミングの話題を理解する.]
asyncとawaitキーワード
非同期メソッドは、メソッド署名にasyncキーワードでマークする方法です.1つ以上のawait文を含めることができます.awaitは一元演算子-待機オペランドであり、待機する必要があるメソッドの名前であることに注意してください.awaitキーワードに遭遇したポイントを一時停止ポイントと呼びます.次のコード・セグメントでは、asyncキーとawaitキーの使用方法について説明します.
public async Task GetDataAsync()
{
  using (SqlConnection connection = new
  SqlConnection(connectionString)
  {
     await connection.OpenAsync();
     //Other code   
  }
}

非同期継続
非同期メソッドでawaitキーワードを使用すると、このメソッドはステータスマシン内で分割されます.awaitキーワードは、現在の同期コンテキストを取得します.その後、待機しているタスクが実行されると、ステータスマシンは呼び出しメソッドのコードの実行を再開します.これを継続と呼ぶ.継続は、キューに並んでいる可能性のある他の継続を待たなければならないことに注意してください.最も重要なのは、ASP.Netでは、所定の時点で1つの継続しか実行できません.
待機中のタスクが実行される準備ができている場合、スレッドプール内のスレッドは要求コンテキストに入り、非同期プロセッサの実行を再開します.要求コンテキストの再入力は、HttpContextの設定を含む複数のタスクに関連するため、高価な操作である.Currentと現在のスレッドの識別と地域性.
コンテキストの同期
ExecutionContextには、プログラムが実行中の現在の環境またはコンテキストに関するメタデータが含まれます.Net FrameworkのSystem.Threadingネーミングスペースには、実行コードの場所を示すSynchronizationContextが用意されています.
ただし、注意してください、ASP.Net CoreにはSynchronizationContextクラスはありません.これはASPのためです.Net Coreにおける非同期化と待機メカニズムが最適化され、簡略化されている:使用と性能を容易にするために、ASP.Net CoreからAspNetSynchronizationContextが削除されました.非同期ハンドラがASP.Net Coreで実行を再開すると、スレッドプールのスレッドが実行を続行します.コンテキストキューは回避されました.
ConfigureAwait(false)
非同期ハンドラは、元のスレッド(開始スレッド)で実行を再開します.他の操作がこのスレッドを制御している場合は、操作が制御を放棄するまでハンドラが待機する必要があります.
でも、コードでConfigureAwait(false)を使用する場合は、元のスレッドを待つ必要がなく、任意のスレッドで続行できます.つまり、ConfigureAwait(false)メソッドを使用すると、取得したコンテキスト(つまり、呼び出し元のコンテキスト)でタスクが再開されないことを確認できます.古いASP.Netでこのメソッドを使用してデッドロックを回避するのは良い方法です.
別のスレッドで実行を続行すると、スレッド同期コンテキストおよびすべての地域情報または言語情報(すなわち、書き込みシステム、カレンダー、日付、数値フォーマットなど)が失われます.これらの情報は、コール待ち前に保存し、新しいスレッドで再適用できます.
注意してください、ASP.Net Coreでは、コンフィギュレーションAwait(false)の呼び出しは不要であり、アクションは実行されません.同期コンテキストはASP.Net Coreには存在しないため、コンフィギュレーションAwait(false)をASP.Net Coreに含める必要はありませんが、それを含めて危害はありません.ライブラリコードでコンフィギュレーションAwaitを使用する必要があります.(false)ライブラリは他のアプリケーションで再利用できるためです.
避けるNet Coreでの暗黙的並列
ASP.Net Coreで作業する場合は、暗黙的な並列性を認識する必要があります.暗黙的な並列が何なのか、私たちがなぜ関心を持っているのかを説明しましょう.旧版ASP.Netでは、同期コンテキストがあり、非同期継続は任意のスレッドで実行できます.ただし、リクエストコンテキストでは、コードを実行するスレッドは一度に1つしかありません.
それに比べてASP.Net Coreには同期コンテキストが欠けており、非同期継続は任意のスレッドで実行できます.最も重要なのは、継続が複数のスレッド上で並列に実行されることである.これが問題です.この点をコードの例で理解しましょう.
以下のコードはASP.Netで正常に動作.
private HttpClient _httpClient = new HttpClient();
public Task ExecuteParallelJobs(List urls)
{
    List result = new List();
    var jobs = new Task[5];
    for(int i=0; i < 5; i++)
    {
      job[i] = GetDataAsync(result, urls[i].ToString());
    }
   await Task.WhenAll(jobs);
   return result;
}
private async Task GetDataAsync(List result, string url)
{
   var data = await _client.GetStringAsync(url);
   result.Add(data);
}

GetDataAsyncメソッドの文result.Add(data)はリクエストコンテキストで実行されます.したがって、ASP.Netでは一度に1つのスレッドのみで実行できます.ただし、同じ文result.Add(data)は、resultという共有セットインスタンスを保護することなく、ASP.Net Coreの複数のスレッドによって実行されます.
この問題を解決するには、次のコードクリップに示すように、ConcurrentBagやConcurrentStackのような同時コレクションを使用するか、lockキーワードを使用します.
private async Task GetDataAsync(List result, string url)
{
   var data = await _client.GetStringAsync(url);
   lock(result)
   {
     result.Add(data);
   } 
}

非同期プログラミングにより、アプリケーションのプライマリ・スレッドや実行スレッドをブロックすることなく、リソースが密集している操作を実行できます.非同期プログラミングを正しく使用すると、アプリケーションの伸縮性が大幅に向上します.ただし、推奨の方法とガイドラインを遵守し、ASPに注意してください.Net Coreと旧版ASP.Net間の違い.
翻訳:https://www.infoworld.com/article/3403346/how-to-use-async-and-await-in-net-core.html
.Netcore非同期プログラミング