等待一系列任务按顺序运行 [英] Awaiting a sequence of tasks to run sequentially

查看:45
本文介绍了等待一系列任务按顺序运行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个通用方法来等待一系列任务按顺序完成,以检索每个任务的结果.这是我创建的代码:

I would like to create a generic method to await for a sequence of tasks to finish sequentially, retrieving the result of each one. This is the code I've created:

public static class TaskMixin 
{
    public static async Task<IEnumerable<T>> AwaitAll<T>(this IEnumerable<Task<T>> tasks)
    {
        var results = new List<T>();
        foreach (var t in tasks)
        {
            results.Add(await t);
        }

        return results;
    }
}

是否有更好的内置方法?

Is there a better or built-in way to do it?

在编写上述方法之前,我尝试使用内置的 Task.WhenAll 方法,但是这给我带来了麻烦,因为这些任务使用的是实体框架的 DbContext 似乎同时运行.

Before writing the above method I tried with the built-in Task.WhenAll method, but it caused me troubles because the tasks are using an Entity Framework's DbContext and they seem to run concurrently.

这是我使用 Task.WhenAll 时遇到的异常.

This is the exception I got when I used Task.WhenAll.

在此上下文中,第二个操作在上一个操作之前开始异步操作完成

A second operation started on this context before a previous asynchronous operation completed

推荐答案

无法确保传递给此方法的任务尚未运行,实际上它们可能已经启动了热门任务.如果任务已经在运行,那么您只需要依次等待它们即可.如果希望操作按顺序运行,则需要调用按顺序返回任务的方法.

There's no way of ensuring that the tasks passed to this method are not already running, in fact they probably are already started hot tasks. If the tasks are already running then your only awaiting them sequentially. If you want operations to run sequentially then you need to invoke the methods that return your tasks sequentially.

或者对于EF的 DbContext ,通常最好为每个请求使用新的 DbContext .但是,如果您执行许多并行查询,那么您可能会以错误的方式来解决问题.许多并行查询并不一定意味着您的查询将运行得更快.

Or in the case of EF's DbContext it's typically best to use a new DbContext for each request. But if your doing many parallel queries then you might be approaching the problem the wrong way. Many parallel queries doesn't necessarily mean your queries are going to run faster.

不过,您可以像下面这样通过获取 Func< Task< T>> 委托来顺序地抽象出正在运行的操作:

You can however abstract away running operations sequentially by taking a Func<Task<T>> delegate like this:

public async Task<IEnumerable<T>> RunSequentiallyAsync<T>(Func<Task<T>>[] operations)
{
    var results = new List<T>();
    foreach (var op in operations)
    {
        results.Add(await op());
    }
    return results;
}

这篇关于等待一系列任务按顺序运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆