私は現在「C# における並行処理のクックブックスティーブン・クリアリー著の「」を読んでいて、次のテクニックに気づきました。
var completedTask = await Task.WhenAny(downloadTask, timeoutTask);
if (completedTask == timeoutTask)
return null;
return await downloadTask;
downloadTask
は の呼び出しでありhttpclient.GetStringAsync
、timeoutTask
を実行していますTask.Delay
。
タイムアウトしなかった場合、 はすでに完了しています。タスクがすでに完了しているのに、downloadTask
を返すのではなく 2 番目の await を実行する必要があるのはなぜですか?downloadTask.Result
ベストアンサー1
すでにいくつかの良い回答やコメントがありますが、私も一言言わせていただきます...
私が(または)await
よりも を好む理由は2つあります。1つ目は、エラー処理が異なることです。 は例外を でラップしません。理想的には、非同期コードは、特にResult
Wait
await
AggregateException
AggregateException
望むに。
2つ目の理由はもう少し微妙です。私のブログ(および本)で説明しているように、Result
/Wait
デッドロックを引き起こす可能性がある、 そしてasync
メソッド内で使用すると、さらに微妙なデッドロックを引き起こす可能性があるResult
. コードを読んでいてまたは を見つけたらWait
、それはすぐに警告フラグになります。Result
/ はWait
、絶対に確実タスクがすでに完了していることを示します。これは一目で確認するのが難しいだけでなく (実際のコードでは)、コードの変更に対しても脆弱です。
Result
それはそうでWait
あるべきだと言っているわけではない一度もない使用できます。私は自分のコードで以下のガイドラインに従っています。
- アプリケーション内の非同期コードでは のみを使用できます
await
。 - 非同期ユーティリティ コード (ライブラリ内) では、コードが本当に必要とする場合に
Result
/ を使用することがあります。このような使用法にはコメントを付ける必要があるでしょう。Wait
- 平行タスクコードでは
Result
と を使用できますWait
。
(1) は圧倒的に一般的なケースであるため、私はawait
どこでもこれを使用し、他のケースを一般規則の例外として扱う傾向があることに注意してください。