私の知る限り、ランタイムが以下のステートメントに出くわすと、非同期で呼び出されるメソッド(この例ではsomeCall()
)へのコールバックとして関数の残りの部分をラップします。この場合、anotherCall()
はsomeCall()
へのコールバックとして実行されます。
_ await someCall();
await anotherCall();
_
ランタイムを次のように実行できるかどうか疑問に思います。非同期でsomeCall()
を呼び出し、すぐに呼び出し元のスレッドに戻ってから、同様にanotherCall()
を呼び出します(someCall
が完了するのを待たずに)。非同期で実行するにはこれらの2つのメソッドが必要であり、これらの呼び出しは単に起動して呼び出しを忘れると仮定するためです。
async
とawait
だけを使用してこのシナリオを実装することは可能ですか(古いbegin
/end
メカニズムを使用していません)?
Async/awaitには、WhenAll
やWhenAny
など、並列合成を支援するいくつかの演算子が含まれています。
var taskA = someCall(); // Note: no await
var taskB = anotherCall(); // Note: no await
// Wait for both tasks to complete.
await Task.WhenAll(taskA, taskB);
// Retrieve the results.
var resultA = taskA.Result;
var resultB = taskB.Result;
最も簡単な方法は、おそらくこれを行うことです。
var taskA = someCall();
var taskB = someOtherCall();
await taskA;
await taskB;
結果の値が必要な場合、これは特に便利です。
var result = await taskA + await taskB;
したがって、taskA.Result
を実行する必要はありません。
TaskEx.WhenAll
は、2つが互いに待機するよりも速い場合があります。パフォーマンスの調査を行っていないのでわかりませんが、問題が発生しない限り、特に結果の値がわからない場合は、2つの連続した待機の方が読みやすいと思います。
.NET 4.5を使用している場合、非同期CTPは不要になりました。非同期機能はコンパイラーによって実装されるため、.NET 4アプリで使用できますが、コンパイルするにはVS2012が必要です。
TaskExはもう必要ありません。 CTPは既存のフレームワークを変更できなかったため、拡張機能を使用して、言語が5.0で処理することを実現しました。タスクを直接使用するだけです。
そこで、これにより、TaskExをTaskに置き換えることで、コードを書き直しました(Stephen Clearyが回答)。
var taskA = someCall(); // Note: no await
var taskB = anotherCall(); // Note: no await
// Wait for both tasks to complete.
await Task.WhenAll(taskA, taskB);
// Retrieve the results.
var resultA = taskA.Result;
var resultB = taskB.Result;