さて、2つ目は簡単なものなので、それを処理しましょう。
2番目のタスクではt2
、の結果に対して何もしませんTask.Delay(1000)
。あなたはawait
それをしません、あなたはそれをしませんWait
、等。方法がそうでないことを考えると、async
私はあなたがそれがブロッキング待機であることを意図したと思いました。Wait()
これを行うには、呼び出しの最後に追加しDelay
てブロッキング待機にするか、またはを使用しますThread.Sleep()
。
最初のタスクでは、を使用しているという事実に噛まれていますvar
。使用しない場合に何が起こっているかがより明確になりますvar
:
Task<Task<int>> t1 = Task.Factory.StartNew(async () =>
{
await Task.Delay(2000);
return 2;
});
のだけでint
なく、のタスクのタスクを返します。内側のタスクの開始が完了するとすぐに、外側のタスクが「完了」します。使用するときは、外側のタスクがいつ終了するかを気にせず、内側のタスクがいつ終了するかを気にします。これを処理する方法はいくつかあります。1つはを使用することです。Task
int
WhenAll
Unwrap
Task<int> t1 = Task.Factory.StartNew(async () =>
{
await Task.Delay(2000);
return 2;
}).Unwrap();
これで、期待どおりTask<int>
にWhenAll
なり、少なくとも2000ミリ秒かかります。await
同じことを行うために別の呼び出しを追加することもできます。
Task<int> t1 = await Task.Factory.StartNew(async () =>
{
await Task.Delay(2000);
return 2;
});
コメントでsvickが述べたように、別のオプションは、Task.Run
の代わりに使用することですStartNew
。 Task.Run
を取り、aFunc<Task<T>>
を返し、Task<T>
それらを自動的にアンラップするメソッド用の特別なオーバーロードのセットがあります。
Task<int> t1 = Task.Run(async () =>
{
await Task.Delay(2000);
return 2;
});
このため、Task.Run
非同期ラムダを作成する場合は、この問題を「処理」するため、デフォルトのオプションとして使用することをお勧めします。ただし、を使用できない複雑なケースでは注意するのが最善ですTask.Run
。
最後に、あなたがしなかったオプションに行き着きます。これは、この場合、おそらく実際に行うべきことです。すでにタスクを返しているのでTask.Delay
、そもそもタスクを入れる必要はありませんStartNew
。ネストされたタスクを作成して使用Unwrap
するのではなく、そもそもそれをラップすることはできません。
var t3 = Task.Delay(3000);
await Task.WhenAll(t1, t2, t3);
あなたが実際に一定の時間だけ待ちたいのなら、それはあなたがしなければならないことです。