2016-10-21 4 views
3

task.Resultasyncメソッドで呼び出すと、デッドロックが発生する可能性があることをご理解ください。私は質問に別のひねりがありますが...タスクが完了したことを知っていれば、非同期メソッドでtask.Resultを呼び出すことはできますか?

私はこのパターンをたくさんしています。私は同じタイプの結果を返すいくつかのタスクを持っているので、それらを一度にすべて待つことができます。でも、私は別に結果を処理したい:

Task<int> t1 = m1Async(); 
Task<int> t2 = m2Async(); 
await Task.WhenAll(t1, t2); 

それは私が知っているので、タスクが完了しましたが、ここではResultを呼び出すためにOKですか?

int result1 = t1.Result; 
int result2 = t2.Result; 

それとも、私はまだawaitを使用する必要があります...それだけで冗長ようだと、私は結果を処理する必要があるかに応じて、ビット醜いことができます。

int result1 = await t1; 
int result2 = await t2; 

更新:誰かが私の質問をマークこれの複製として:Awaiting multiple Tasks with different results。 質問は異なるので、私は検索でそれを見つけられませんでしたが、そこに詳細な回答の1つが質問されるかもしれません。

+1

はい、わかっても結果を呼び出すことは可能です。しかし、WhenAllの後に.Resultを呼び出し、t1またはt2が例外を投げた場合、.Resultは問題になります。 –

+0

私はいくつかの投稿が例外を伴う異なる動作を指しているのを見ましたが、私はそれをすべて理解するためにはそれをさらに深く掘り下げる必要があります。迅速な対応をありがとう! – Cary

+0

あなたが知っておくべき1つのこと。完了した状態のタスクで 'await'を呼び出すと、パフォーマンスオーバーヘッドは0になります。生成されるステートマシンは、その状態をチェックし、基本的に '.Result'を内部的に呼び出すようにスキップします(' .GetAwaiter()。GetResult() 'を実際に呼び出しますが、' .Result' )。だから、すでに 'async'とマークされているメソッドの中で' .Result'を使う魅力的な理由はありません。 –

答えて

5

すでにawaitを行った後にt1.Resultを使用した場合、本質的に間違ったことや悪いことはありませんが、将来の問題が発生する可能性があります。メソッドの開始時に誰かがコードを変更し、タスクが正常に完了しなくなった場合はどうなりますか?そして、もしあなたがこの仮定を下すあなたのコードをさらに見ていなければどうでしょうか?

最初のawaitの戻り値を使用するほうがよいかもしれません。誰かが最初awaitで台無し場合

Task<int> t1 = m1Async(); 
Task<int> t2 = m2Async(); 
var results = await Task.WhenAll(t1, t2); 

int result1 = results[0]; 
int result2 = results[1]; 

そうすれば、彼らはあなたのコードは、後でその結果に依存していることを知ってフォローするために自然な接続があります。

Task.WhenAll()が実際にあなたに価値を与えているかどうかを検討することもできます。失敗したタスクと失敗したタスクの違いを伝えたい場合を除き、タスクを個別に待つのは簡単かもしれません。

Task<int> t1 = m1Async(); 
Task<int> t2 = m2Async(); 

int result1 = await t1; 
int result2 = await t2; 
+0

WhenAllの返品を使用して良い点。しかし、より複雑なシナリオで結果を整理するために毛むくじゃらする可能性があります。そして、もし私が個別に仕事を待っていたら、私は呼び出しをシリアル化していませんか? – Cary

+2

@Cary:相手を呼び出す前に最初のコールを待っている場合にのみ、コールをシリアライズしています。 'mAsAsync()'の結果を '待つ 'の前に' m2Async() 'を呼び出すと、実行がスコープから外れる前に2番目の呼び出しが進行します。 – StriplingWarrior

0

ドキュメントはTask.Resultit is equivalent to calling the Wait methodことを言います。

そしてときWait「がTask.Waitは何をしますか?」

を...タスクが完了するまで実行した場合

と呼ばれ、待っが正常に戻ります。

https://blogs.msdn.microsoft.com/pfxteam/2009/10/15/task-wait-and-inlining/から)

だからあなたはあなたがTask.Resultを呼び出すとき、それはあなたが言及したデッドロックにつながるない成功裏に返すことを想定することができます。

関連する問題