パフォーマンスの観点から、これら2つのメソッドはGetAllWidgets()
とGetAllFoos()
を並行して実行しますか?
一方を他方よりも使用する理由はありますか?コンパイラの背後で多くのことが起こっているようですので、わかりません。
============= MethodA:複数の待機を使用する=====================
public async Task<IHttpActionResult> MethodA()
{
var customer = new Customer();
customer.Widgets = await _widgetService.GetAllWidgets();
customer.Foos = await _fooService.GetAllFoos();
return Ok(customer);
}
=============== MethodB:Task.WaitAllを使用する=====================
public async Task<IHttpActionResult> MethodB()
{
var customer = new Customer();
var getAllWidgetsTask = _widgetService.GetAllWidgets();
var getAllFoosTask = _fooService.GetAllFos();
Task.WaitAll(new List[] {getAllWidgetsTask, getAllFoosTask});
customer.Widgets = getAllWidgetsTask.Result;
customer.Foos = getAllFoosTask.Result;
return Ok(customer);
}
=====================================
最初のオプションは、2つの操作を同時に実行しません。最初のものを実行し、その完了を待ち、その後にのみ2番目のものを待ちます。
2番目のオプションは両方を同時に実行しますが、同期的に(つまり、スレッドをブロックしている間)待機します。
最初のオプションは2番目のオプションよりも完了が遅く、2番目のオプションは必要なくスレッドをブロックするため、両方のオプションを使用しないでください。
Task.WhenAll
を使用して、両方の操作を非同期で待機する必要があります。
public async Task<IHttpActionResult> MethodB()
{
var customer = new Customer();
var getAllWidgetsTask = _widgetService.GetAllWidgets();
var getAllFoosTask = _fooService.GetAllFos();
await Task.WhenAll(getAllWidgetsTask, getAllFoosTask);
customer.Widgets = await getAllWidgetsTask;
customer.Foos = await getAllFoosTask;
return Ok(customer);
}
Task.WhenAll
が完了した後、両方のタスクがすでに完了しているので、それらを待つことはすぐに完了することに注意してください。
短い答え:いいえ。
_Task.WaitAll
_はブロックしているため、await
はタスクが検出されるとすぐにタスクを返し、関数と継続の残りの部分を登録します。
探していた「バルク」待機メソッドは_Task.WhenAll
_で、これは実際に新しいTask
を作成し、関数に渡されたすべてのタスクが完了すると終了します。
そのように:await Task.WhenAll({getAllWidgetsTask, getAllFoosTask});
それはブロッキング問題です。
また、最初の関数は両方の関数を並行して実行しません。 await
でこれを機能させるには、次のように記述する必要があります。
_var widgetsTask = _widgetService.GetAllWidgets();
var foosTask = _fooService.GetAllWidgets();
customer.Widgets = await widgetsTask;
customer.Foos = await foosTask;
_
これにより、最初の例は_Task.WhenAll
_メソッドと非常によく似た動作をします。
2番目のオプションのみがそれらを並行して実行します。最初の呼び出しは、各呼び出しを順番に待機します。
Asyncメソッドを呼び出すとすぐに実行が開始されます。現在のスレッドで実行する(したがって、同期的に実行する)か、非同期で実行するかを判断することはできません。
したがって、最初の例では、最初のメソッドが作業を開始しますが、その後、awaitを使用してコードのフローを人為的に停止します。したがって、2番目のメソッドは、最初のメソッドの実行が完了する前に呼び出されません。
2番目の例は、待機でフローを停止せずに両方のメソッドを呼び出します。したがって、メソッドが非同期の場合、潜在的に並列で実行されます。