私は現在、Stephen Clearyによる「Concurrency in C#Cookbook」を読んでいますが、次のようなテクニックに気付きました。
var completedTask = await Task.WhenAny(downloadTask, timeoutTask);
if (completedTask == timeoutTask)
return null;
return await downloadTask;
downloadTaskhttpclient.GetStringAsyncへの呼び出しです。timeoutTaskTask.Delayを実行しています。
タイムアウトしなかった場合、downloadTaskはすでに完了しています。タスクが既に完了しているため、なぜdownloadTask.Resultを返さずにもう一度待つ必要があるのでしょうか。
ここにはすでにいくつかの良い答え/コメントがありますが、ただ参加するには...
私が好む理由は2つあります。awaitオーバーResult(またはWait) 1つは、エラー処理が異なることです。awaitで例外をラップしません。AggregateException。理想的には、非同期コードは決して対処する必要はないはずです。AggregateException特に明記しない限り、望むに。
第二の理由はもう少し微妙です。私のブログで(そして本の中で)説明しているように、Result/Waitデッドロックを引き起こす可能性があります、そしてで使用すると、さらに微妙なデッドロックが発生する可能性があります。async方法。だから、コードを読んでいると、ResultまたはWait、それは即時の警告フラグです。のResult/Waitあなたがいる場合だけ正しいです絶対確実タスクは既に完了していること。一見して(実世界のコードで)これを見るのが難しいだけでなく、それはまたコード変更に対してより脆弱です。
それは言うことではありませんResult/Waitすべき決して利用される。私は自分のコードでこれらのガイドラインに従います。
await。Result/Waitコードが本当にそれを要求しているなら。そのような用法はおそらくコメントがあるはずです。ResultそしてWait。(1)がはるかに一般的なケースであることに注意してください。await他の場合は一般的な規則の例外として扱ってください。
awaitを防ぐAggregateExceptionラッパー。AggregateException非同期プログラミングではなく、並列プログラミング用に設計されています。 - Stephen ClearyWaitに参加することでした動的タスク並列処理
Taskインスタンス。非同期を待つためにそれを使うTaskインスタンスは危険です。マイクロソフトは、新しい「約束」の導入を検討しました。タイプ、しかし既存のものを使用することを選びましたTask代わりに既存のものを再利用することのトレードオフTask非同期タスクのタイプは、非同期コードで使用してはいけないいくつかのAPIを使用することになります。 - Stephen Cleary
これは理にかなっているtimeoutTaskの製品ですTask.Delayそれが本の中にあると私は信じています。
Task.WhenAny戻るTask<Task>内部タスクは引数として渡したものの1つです。このように書き直すことができます。
Task<Task> anyTask = Task.WhenAny(downloadTask, timeoutTask);
await anyTask;
if (anyTask.Result == timeoutTask)
return null;
return downloadTask.Result;
どちらの場合も、downloadTaskすでに完成していますが、非常に小さな違いがあります。return await downloadTaskそしてreturn downloadTask.Result。それは後者が投げるということですAggregateExceptionコメントで@KirillShlenskiyが指摘したように、これは元の例外をすべてラップします。前者は元の例外を再度スローするだけです。
どちらの場合も、例外を処理する場所はどこでも、確認する必要があります。AggregateExceptionとにかく、その内部の例外は、エラーの原因に到達するために。
downloadTaskそしてtimeoutTask?彼らは何をしますか? - Mike PerrenoudAggregateExceptionとResult対最初の例外ExceptionDispatchInfoとawait) Stephen Toubの「.NET 4.5でのタスク例外処理」で詳しく説明しています。blogs.msdn.com/b/pfxteam/archive/2011/09/28/…) - Kirill Shlenskiy