运行多个asynchronous任务,并等待他们完成
我需要在控制台应用程序中运行多个asynchronous任务,并等待它们完成后再进一步处理。
那边有很多文章,但是我读得越多,似乎就越觉得困惑。 我已经阅读并理解了任务库的基本原理,但是我显然错过了某处的链接。
我明白,可以将任务链接起来,让他们在另一个完成后开始工作(这几乎是我读过的所有文章的场景),但是我希望所有的任务同时运行,而且我想知道一次他们都完成了。
这样的场景最简单的实现是什么?
两个答案都没有提到候选人的Task.WhenAll
。当Task.WhenAll
:
var task1 = DoWorkAsync(); var task2 = DoMoreWorkAsync(); await Task.WhenAll(task1, task2);
Task.WaitAll
和Task.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 Task
或WaitAll
,并且会阻止与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