运行多个异步任务,并等待他们全部完成运行多个异步任务,并等待他们全部完成(Running multi

2019-05-09 07:32发布

我需要在控制台应用程序运行多个异步任务,并等待他们的所有进一步的处理之前完成。

有很多文章在那里,但我似乎得到更多的困惑我越读。 我已阅读并理解任务库的基本原则,但我清楚地缺少的环节上。

据我所知,这是可能的连锁任务,使他们另一个完成之后启动(这是几乎所有我读过的文章的情况下),但我想我所有的在同一时间运行的任务,我想知道,一旦他们都完成了。

什么是像这样的情况下最简单的实现?

Answer 1:

这两个答案没有提及awaitable Task.WhenAll

var task1 = DoWorkAsync();
var task2 = DoMoreWorkAsync();

await Task.WhenAll(task1, task2);

之间的主要区别Task.WaitAllTask.WhenAll在于,前者将阻止(类似于使用Wait上一个任务),而后者不会,也被期待已久,产生控制权返回给调用者,直到所有任务完成。

更何况,异常处理的区别:

Task.WaitAll

至少任务实例之一被取消了 - 或者一个异常被任务实例中的至少一个的执行过程中抛出。 如果任务被取消,该AggregateException包含在其InnerExceptions收集的OperationCanceledException。

Task.WhenAll

如果有任何的供应任务故障状态结束,返回的任务也将完成在故障状态,其中它的异常将包含一套从每个供应任务展开异常的聚集。

如果没有提供的任务故障,但其中至少有一个被取消,返回的任务将在取消状态结束。

如果没有任务故障,没有任务被取消,所产生的任务将在RanToCompletion状态结束。 如果所提供的阵列/枚举不包含任何任务,之前它返回给调用者返回的任务将立即转换到一个RanToCompletion状态。



Answer 2:

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

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

Task.WaitAll(TaskList.ToArray());


Answer 3:

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

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));

或与异步拉姆达:

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


Answer 4:

您可以使用WhenAll它会返回一个awaitable TaskWaitAll它没有返回类型,并会阻止进一步的代码执行simular到Thread.Sleep直到所有的任务都完成,取消或故障。

var tasks = new Task[] {
    TaskOperationOne(),
    TaskOperationTwo()
};

Task.WaitAll(tasks);
// or
await Task.WhenAll(tasks);

如果你想在praticular顺序运行任务,就可以得到灵感的形式这 anwser。



Answer 5:

你想链中的Task S,或者他们能以并行的方式来调用?

对于链接
只是这样做

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

不要忘记检查前面的Task实例中的每个ContinueWith ,因为它可能会出现故障。

对于平行的方式
最简单的方法,我碰到: Parallel.Invoke否则有Task.WaitAll或者你甚至可以使用WaitHandle S代表做了倒计时左零个操作(请等一下,还有一个新的类: CountdownEvent ),或...



Answer 6:

这是我与阵列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


Answer 7:

然而,另一种答案......但我通常发现自己在一个情况下,我需要同时读取数据,然后把它放到变量,如:

var cats = new List<Cat>();
var dog = new Dog();

var loadDataTasks = new Task[]
{
    Task.Run(async () => cats = await LoadCatsAsync()),
    Task.Run(async () => dog = await LoadDogAsync())
};

try
{
    await Task.WhenAll(loadDataTasks);
}
catch (Exception ex)
{
    // handle exception
}


Answer 8:

我准备了一段代码向你展示了如何使用任务其中一些场景。

    // method to run tasks in a parallel 
    public async Task RunMultipleTaskParallel(Task[] tasks) {

        await Task.WhenAll(tasks);
    }
    // methode to run task one by one 
    public async Task RunMultipleTaskOneByOne(Task[] tasks)
    {
        for (int i = 0; i < tasks.Length - 1; i++)
            await tasks[i];
    }
    // method to run i task in parallel 
    public async Task RunMultipleTaskParallel(Task[] tasks, int i)
    {
        var countTask = tasks.Length;
        var remainTasks = 0;
        do
        {
            int toTake = (countTask < i) ? countTask : i;
            var limitedTasks = tasks.Skip(remainTasks)
                                    .Take(toTake);
            remainTasks += toTake;
            await RunMultipleTaskParallel(limitedTasks.ToArray());
        } while (remainTasks < countTask);
    }


文章来源: Running multiple async tasks and waiting for them all to complete