Task.WhenAll(taskList).Wait() 和 Task.WaitAll(taskList) 一样吗?
Is Task.WhenAll(taskList).Wait() the same as Task.WaitAll(taskList)?
这些行的行为是否完全相同(包括通过 AggregateException 进行的异常处理)?
Task.WhenAll(taskList).Wait()
Task.WaitAll(taskList)
谢谢
让我们通过实验找出答案:
var task1 = Task.FromResult(13);
var task2 = Task.FromCanceled<int>(new CancellationToken(true));
var task3 = Task.FromCanceled<int>(new CancellationToken(true));
var task4 = Task.FromException<int>(new ApplicationException());
var task5 = Task.FromException<int>(new OverflowException());
Test("Successful+Canceled+Canceled", new[] { task1, task2, task3 });
Test("Successful+Failed+Failed", new[] { task1, task4, task5 });
Test("Successful+Canceled+Failed+Failed", new[] { task1, task2, task4, task5 });
Test("Successful+Canceled+Canceled+Failed", new[] { task1, task2, task3, task4 });
static void Test(string title, Task<int>[] tasks)
{
Console.WriteLine();
Console.WriteLine(title);
try { Task.WaitAll(tasks); }
catch (AggregateException ex)
{
Console.WriteLine($"WaitAll(): {ToString(ex)}");
}
try { Task.WhenAll(tasks).Wait(); }
catch (AggregateException ex)
{
Console.WriteLine($"WhenAll.Wait(): {ToString(ex)}");
}
}
static string ToString(AggregateException aex) {
return $"({aex.InnerExceptions.Count}) " +
String.Join(", ", aex.InnerExceptions.Select(ex => ex.GetType().Name));
}
输出:
Successful+Canceled+Canceled
WaitAll(): (2) TaskCanceledException, TaskCanceledException
WhenAll.Wait(): (1) TaskCanceledException
Successful+Failed+Failed
WaitAll(): (2) ApplicationException, OverflowException
WhenAll.Wait(): (2) ApplicationException, OverflowException
Successful+Canceled+Failed+Failed
WaitAll(): (3) TaskCanceledException, ApplicationException, OverflowException
WhenAll.Wait(): (2) ApplicationException, OverflowException
Successful+Canceled+Canceled+Failed
WaitAll(): (3) TaskCanceledException, TaskCanceledException, ApplicationException
WhenAll.Wait(): (1) ApplicationException
我们看到的是 Task.WaitAll()
method propagates the exceptions of the tasks as they are, while the Task.WhenAll()
.Wait()
方法仅传播一个 TaskCanceledException
,并且仅在未发生其他类型的异常时才传播。
还应该提到的是,使用 Task.WaitAll
您可以获得更多开箱即用的选项,例如 millisecondsTimeout
或 cancellationToken
,或两者兼而有之。
这些行的行为是否完全相同(包括通过 AggregateException 进行的异常处理)?
Task.WhenAll(taskList).Wait()
Task.WaitAll(taskList)
谢谢
让我们通过实验找出答案:
var task1 = Task.FromResult(13);
var task2 = Task.FromCanceled<int>(new CancellationToken(true));
var task3 = Task.FromCanceled<int>(new CancellationToken(true));
var task4 = Task.FromException<int>(new ApplicationException());
var task5 = Task.FromException<int>(new OverflowException());
Test("Successful+Canceled+Canceled", new[] { task1, task2, task3 });
Test("Successful+Failed+Failed", new[] { task1, task4, task5 });
Test("Successful+Canceled+Failed+Failed", new[] { task1, task2, task4, task5 });
Test("Successful+Canceled+Canceled+Failed", new[] { task1, task2, task3, task4 });
static void Test(string title, Task<int>[] tasks)
{
Console.WriteLine();
Console.WriteLine(title);
try { Task.WaitAll(tasks); }
catch (AggregateException ex)
{
Console.WriteLine($"WaitAll(): {ToString(ex)}");
}
try { Task.WhenAll(tasks).Wait(); }
catch (AggregateException ex)
{
Console.WriteLine($"WhenAll.Wait(): {ToString(ex)}");
}
}
static string ToString(AggregateException aex) {
return $"({aex.InnerExceptions.Count}) " +
String.Join(", ", aex.InnerExceptions.Select(ex => ex.GetType().Name));
}
输出:
Successful+Canceled+Canceled
WaitAll(): (2) TaskCanceledException, TaskCanceledException
WhenAll.Wait(): (1) TaskCanceledException
Successful+Failed+Failed
WaitAll(): (2) ApplicationException, OverflowException
WhenAll.Wait(): (2) ApplicationException, OverflowException
Successful+Canceled+Failed+Failed
WaitAll(): (3) TaskCanceledException, ApplicationException, OverflowException
WhenAll.Wait(): (2) ApplicationException, OverflowException
Successful+Canceled+Canceled+Failed
WaitAll(): (3) TaskCanceledException, TaskCanceledException, ApplicationException
WhenAll.Wait(): (1) ApplicationException
我们看到的是 Task.WaitAll()
method propagates the exceptions of the tasks as they are, while the Task.WhenAll()
.Wait()
方法仅传播一个 TaskCanceledException
,并且仅在未发生其他类型的异常时才传播。
还应该提到的是,使用 Task.WaitAll
您可以获得更多开箱即用的选项,例如 millisecondsTimeout
或 cancellationToken
,或两者兼而有之。