WaitAll与WhenAll

Async CTP中的Task.WaitAll()TaskEx.WhenAll()什么区别? 你能提供一些示例代码来说明不同的用例吗?

Task.WaitAll阻止当前线程,直到一切完成。

TaskEx.WhenAll返回一个代表等待一切完成的动作的任务

这意味着从asynchronous方法,您可以使用:

 await TaskEx.WhenAll(tasks); 

这意味着你的方法会在所有事情都完成的时候继续下去,但是你不会把一个线程挂起来,直到那个时候。

尽pipeJonSkeet的回答对我来说以一种非常好的方式来解释差异,但最大的实际区别是exception处理

当任何任务抛出时, Task.WaitAll抛出一个AggregateException ,你可以检查所有抛出的exception。 await Task.WhenAll展开AggregateException和'返回'只有第一个exception。

当下面的程序执行时, 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线程做了一些事情(例如,一个代表故事板中的animation的任务),如果你Task.WaitAll()那么UI线程被阻塞,UI永远不会更新。 如果使用await Task.WhenAll()那么UI线程不会被阻塞,UI将被更新。