运行多个asynchronous任务,并等待他们完成

我需要在控制台应用程序中运行多个asynchronous任务,并等待它们完成后再进一步处理。

那边有很多文章,但是我读得越多,似乎就越觉得困惑。 我已经阅读并理解了任务库的基本原理,但是我显然错过了某处的链接。

我明白,可以将任务链接起来,让他们在另一个完成后开始工作(这几乎是我读过的所有文章的场景),但是我希望所有的任务同时运行,而且我想知道一次他们都完成了。

这样的场景最简单的实现是什么?

两个答案都没有提到候选人的Task.WhenAll 。当Task.WhenAll

 var task1 = DoWorkAsync(); var task2 = DoMoreWorkAsync(); await Task.WhenAll(task1, task2); 

Task.WaitAllTask.WhenAll之间的主要区别在于前者会阻塞(类似于在单个任务中使用Wait ),而后者则不会被等待,从而使控制权返回给调用者,直到所有任务完成。

更有甚者,exception处理有所不同:

Task.WaitAll

至less有一个Task实例被取消了 – 或者 – 在至less执行了一个Task实例的过程中抛出了一个exception。 如果任务被取消,则AggregateException在其InnerExceptions集合中包含OperationCanceledException。

Task.WhenAll

如果任何提供的任务在故障状态下完成,则返回的任务也将以Faulted状态完成,其中的exception将包含每个提供的任务的解包exception集合。

如果没有提供的任务出现故障,但至less其中一个被取消,则返回的任务将以已取消状态结束。

如果没有任何任务出现故障并且没有任何任务被取消,则结果任务将以RanToCompletion状态结束。 如果提供的数组/枚举不包含任务,返回的任务会在返回给调用者之前立即转换为RanToCompletion状态。

你可以创build许多任务,如:

 List<Task> TaskList = new List<Task>(); foreach(...) { var LastTask = new Task(SomeFunction); LastTask.Start(); TaskList.Add(LastTask); } Task.WaitAll(TaskList.ToArray()); 

我见过的最好的select是下面的扩展方法:

 public static Task ForEachAsync<T>(this IEnumerable<T> sequence, Func<T, Task> action) { return Task.WhenAll(sequence.Select(action)); } 

像这样调用它:

 await sequence.ForEachAsync(item => item.SomethingAsync(blah)); 

或者使用asynchronouslambda:

 await sequence.ForEachAsync(async item => { var more = await GetMoreAsync(item); await more.FrobbleAsync(); }); 

你想链接Task ,还是可以以并行方式调用?

链接
只要做一些像

 Task.Run(...).ContinueWith(...).ContinueWith(...).ContinueWith(...); Task.Factory.StartNew(...).ContinueWith(...).ContinueWith(...).ContinueWith(...); 

并且不要忘记检查每个ContinueWith的前一个Task实例,因为它可能有故障。

为了平行的方式
我遇到的最简单的方法: Parallel.Invoke否则有Task.WaitAll或甚至可以使用WaitHandle s做一个倒计时零操作离开(等待,有一个新的类: CountdownEvent ),或…

您可以使用WhenAll ,它会返回一个没有返回types的Waitable TaskWaitAll ,并且会阻止与Thread.Sleep类似的进一步的代码执行,直到所有任务完成,取消或出错。

在这里输入图像描述

 var tasks = new Task[] { await TaskOperationOne(), await TaskOperationTwo() }; Task.WaitAll(tasks); // or await Task.WhenAll(tasks); 

如果你想按照正确的顺序运行这些任务,你可以从这个问题上得到灵感。

这是我如何做一个数组Func <>

 var tasks = new Func<Task>[] { () => myAsyncWork1(), () => myAsyncWork2(), () => myAsyncWork3() }; await Task.WhenAll(tasks.Select(task => task()).ToArray()); //Async Task.WaitAll(tasks.Select(task => task()).ToArray()); //Or use WaitAll for Sync