This question already has answers here:
How to execute each iteration of the loop in one thread with task?

(1个答案)



Using async/await for multiple tasks

(6个答案)


4年前关闭。




我有一个Windows服务,它可以根据计划运行各种作业。在确定要运行的作业之后,调度对象列表将发送到一种方法,该方法遍历list并运行每个作业。问题是,由于外部数据库调用,某些作业最多可能需要10分钟才能运行。

我的目标是在队列中没有一个作业阻塞其他作业,基本上一次只能运行一个以上。我以为使用async和await可以解决这个问题,但是我以前从未使用过。

当前代码:
public static bool Load(List<Schedule> scheduleList)
{
    foreach (Schedule schedule in scheduleList)
    {
        Load(schedule.ScheduleId);
    }

    return true;
}

public static bool Load(int scheduleId)
{
    // make database and other external resource calls
    // some jobs run for up to 10 minutes

    return true;
}

我尝试更新此代码:
public async static Task<bool> LoadAsync(List<Schedule> scheduleList)
{
    foreach (Schedule schedule in scheduleList)
    {
        bool result = await LoadAsync((int)schedule.JobId, schedule.ScheduleId);
    }

    return true;
}

public async static Task<bool> LoadAsync(int scheduleId)
{
    // make database and other external resource calls
    // some jobs run for up to 10 minutes

    return true;
}

问题在于,第一个LoadAsync会等待作业完成,然后再将控制权交还给循环,而不是允许所有作业启动。

我有两个问题:
  • 高级别-aysnc/await是最佳选择,还是我应该使用其他方法?
  • 需要更新哪些内容,以允许循环启动所有作业而不阻塞,但不允许函数在所有作业完成之前返回?
  • 最佳答案


    async-await非常适合您要尝试执行的操作,它可以同时卸载多个IO绑定(bind)任务。



    您的循环当前正在等待,因为您对每个对await的调用LoadAsync。您想要的是同时执行所有命令,而不是等待所有命令使用Task.WhenAll完成:

    public async static Task<bool> LoadAsync(List<Schedule> scheduleList)
    {
       var scheduleTaskList = scheduleList.Select(schedule =>
                              LoadAsync((int)schedule.JobId, schedule.ScheduleId)).ToList();
       await Task.WhenAll(scheduleTaskList);
    
       return true;
    }
    

    08-18 11:09
    查看更多