非同期CTPTask.WaitAll()
との違いは何ですか?Task.WhenAll()
さまざまなユースケースを説明するためのサンプルコードを提供できますか?
4 に答える
Task.WaitAll
すべてが完了するまで、現在のスレッドをブロックします。
Task.WhenAll
すべてが完了するまで待機するアクションを表すタスクを返します。
つまり、非同期メソッドから、次を使用できます。
await Task.WhenAll(tasks);
...つまり、すべてが完了してもメソッドは続行されますが、そのときまでスレッドを拘束してぶらぶらすることはありません。
JonSkeetの回答は、通常は優れた方法で違いを説明していますが、別の違いがあります。例外処理です。
Task.WaitAll
いずれかのタスクがスローされたAggregateException
ときにをスローし、スローされたすべての例外を調べることができます。await
inはラップawait Task.WhenAll
を解除しAggregateException
、'は最初の例外のみを返します。
以下のプログラムを実行するとawait Task.WhenAll(taskArray)
、出力は次のようになります。
19/11/2016 12:18:37 AM: Task 1 started
19/11/2016 12:18:37 AM: Task 3 started
19/11/2016 12:18:37 AM: Task 2 started
Caught Exception in Main at 19/11/2016 12:18:40 AM: Task 1 throwing at 19/11/2016 12:18:38 AM
Done.
以下のプログラムを実行しTask.WaitAll(taskArray)
た場合の出力は次のようになります。
19/11/2016 12:19:29 AM: Task 1 started
19/11/2016 12:19:29 AM: Task 2 started
19/11/2016 12:19:29 AM: Task 3 started
Caught AggregateException in Main at 19/11/2016 12:19:32 AM: Task 1 throwing at 19/11/2016 12:19:30 AM
Caught AggregateException in Main at 19/11/2016 12:19:32 AM: Task 2 throwing at 19/11/2016 12:19:31 AM
Caught AggregateException in Main at 19/11/2016 12:19:32 AM: Task 3 throwing at 19/11/2016 12:19:32 AM
Done.
プログラム:
class MyAmazingProgram
{
public class CustomException : Exception
{
public CustomException(String message) : base(message)
{ }
}
static void WaitAndThrow(int id, int waitInMs)
{
Console.WriteLine($"{DateTime.UtcNow}: Task {id} started");
Thread.Sleep(waitInMs);
throw new CustomException($"Task {id} throwing at {DateTime.UtcNow}");
}
static void Main(string[] args)
{
Task.Run(async () =>
{
await MyAmazingMethodAsync();
}).Wait();
}
static async Task MyAmazingMethodAsync()
{
try
{
Task[] taskArray = { Task.Factory.StartNew(() => WaitAndThrow(1, 1000)),
Task.Factory.StartNew(() => WaitAndThrow(2, 2000)),
Task.Factory.StartNew(() => WaitAndThrow(3, 3000)) };
Task.WaitAll(taskArray);
//await Task.WhenAll(taskArray);
Console.WriteLine("This isn't going to happen");
}
catch (AggregateException ex)
{
foreach (var inner in ex.InnerExceptions)
{
Console.WriteLine($"Caught AggregateException in Main at {DateTime.UtcNow}: " + inner.Message);
}
}
catch (Exception ex)
{
Console.WriteLine($"Caught Exception in Main at {DateTime.UtcNow}: " + ex.Message);
}
Console.WriteLine("Done.");
Console.ReadLine();
}
}
違いの例として、タスクがある場合、UIスレッドで何かを実行します(たとえば、ストーリーボードでアニメーションを表すタスク)。その場合Task.WaitAll()
、UIスレッドはブロックされ、UIは更新されません。を使用するawait Task.WhenAll()
場合、UIスレッドはブロックされず、UIが更新されます。
彼らは何をしますか:
- 内部的には両方とも同じことをします。
違いは何ですか:
- WaitAllはブロッキング呼び出しです
- WhenAll -not-コードは実行を継続します
次の場合に使用します。
- 結果がないと続行できない場合はWaitAll
- WhenAllいつ通知されるだけで、ブロックされない