ASP.NET MVCの非同期コントローラーメソッドに関する記事( http://visualstudiomagazine.com/articles/2013/07/23/async-actions-in-aspnet-mvc-4.aspx )そして私はポイントを逃しているかもしれないと思います。
私が書いたこのメソッドを考えてみましょう。これは、記事の例に非常に似ています。
[HttpGet]
[AsyncTimeout(8000)]
[HandleError(ExceptionType = typeof(TimeoutException), View = "TimedOut")]
public async Task<ActionResult> Index(CancellationToken cancellationToken)
{
WidgetPageViewModel model = new WidgetPageViewModel()
{
toAdd = new Widget()
};
model.all = await _repo.GetAllAsync(cancellationToken);
return View(model);
}
私は物事を理解しているように、これは実行時に物事が展開する方法です:
受信したHTTP要求に対してASP.NETスレッドが作成されます。
このスレッドは(おそらくいくつかの必要な準備作業を行った後)上記のIndex()メソッドに入ります。
実行は「await」キーワードに到達し、別のスレッドでデータ取得プロセスを開始します。
元の "ASP.NET"スレッドは、ハンドラーメソッドを呼び出したコードに戻り、Taskクラスのインスタンスを戻り値として返します。
ハンドラーメソッドを呼び出したインフラストラクチャコードは、実際のActionResultオブジェクトを使用する必要があるポイント(ページのレンダリングなど)に到達するまで、元の "ASP.NET"スレッドで動作し続けます。
次に、呼び出し元はTask.Resultメンバーを使用してこのオブジェクトにアクセスします。これにより、オブジェクト(つまり、「ASP.NET」スレッド)は、上記の手順3で暗黙的に作成されたスレッドを待機します。
私が些細なことと感じている2つのことを除いて、これがawait/asyncなしで同じことと比較して何を達成するかを見ていません。
Awaitによって作成された呼び出し側スレッドとワーカースレッドは、一定期間(上記の#5の「まで」の部分)並行して動作できます。私の直感は、期間がかなり短いということです。インフラストラクチャがコントローラーメソッドを呼び出すとき、私は通常、コントローラーメソッドの多く(もしあれば)をさらに実行する前に、コントローラー呼び出しの実際のActionResultが必要であると考えています。
長時間実行される非同期コントローラー操作のタイムアウトとキャンセルに関連する便利な新しいインフラストラクチャがいくつかあります。
非同期コントローラーメソッドを追加する目的は、ASP.NETワーカースレッドを解放して、実際にHTTP要求に応答することです。これらのスレッドは有限のリソースです。残念ながら、記事で提案されているパターンが実際にこれらのスレッドを節約するためにどのように機能するかはわかりません。そして、それがそうであり、何らかの非ASP.NETスレッドへの要求を処理する負担をなんとかオフロードしても、それは何を達成するのでしょうか?たまたまHTTPリクエストを処理できるスレッドは、一般的なスレッドとは大きく異なりますか?
タスク並列ライブラリ(TPL)を使用しないASP.Netは、スレッドプール内のスレッドの数によって、同時に処理できる要求の数が制限されています。 TPLを使用するASP.Netは、リクエストを処理するマシンのCPU /メモリ/ IOによって制限されます。
タスク並列ライブラリ(TPL)は、ユーザーが思っているようにスレッドを消費しません。タスクはスレッドではなく、いくつかの計算単位のラッパーです。タスクスケジューラは、ビジーでないスレッドで各タスクを実行する責任があります。実行時に、タスクを待機してもスレッドはブロックされません。後で実行できるように実行状態を保留するだけです。
通常、単一のHTTP要求は単一のスレッドによって処理され、応答が返されるまでそのスレッドをプールから完全に削除します。 TPLを使用すると、この制約に拘束されません。入ってくる要求は、プール内の任意のスレッドで実行できる応答を計算するために必要な各計算単位で継続を開始します。このモデルでは、標準のASP.Netよりも多くの同時要求を処理できます。