【问题标题】:How to chain together two collections of Tasks?如何将两个任务集合链接在一起?
【发布时间】:2018-03-15 20:21:35
【问题描述】:

我正在尝试运行一组任务,然后在这些任务完成后,运行一个单独的任务组。本质上,第一个任务集合负责写入一些数据库表,最后一个任务集合将这些表中的数据整理成一个报告表。

我正在使用的代码示例如下:

var dbWriteTasks = clients.Select(c => DoSomeWorkAsync(c)).ToArray();
var dbCollateTasks = clients.Select(c => DoSomeOtherWorkAsync(c));

Task.Factory.ContinueWhenAll(dbWriteTasks, t => dbCollateTasks.ToArray());

这是成功运行第一组任务,但没有运行任何第二组任务,所以我显然做错了什么。

我也试过了,没用:

var dbWriteTasks = clients.Select(c => DoSomeWorkAsync(c)).ToArray();
var dbCollateTasks = clients.Select(c => DoSomeOtherWorkAsync(c)).ToArray();

Task.Factory.ContinueWhenAll(dbWriteTasks, t => dbCollateTasks);

这会运行两组任务,但第二组任务在第一组任务完成插入数据之前开始运行并处理数据...

我还应该提到,我尝试过使用Task.WaitAll 同步运行这两组任务,但这也没有奏效。我正在尝试在 Azure 函数中执行所有这些操作,而 Task.WaitAll 只会导致它停止。

我对 TPL 比较陌生,因此我们将不胜感激任何建议!

【问题讨论】:

    标签: c# multithreading azure task-parallel-library azure-functions


    【解决方案1】:

    使用await Task.WhenAll 代替工厂方法。使用await 可以无缝地创建读起来像同步代码的延续。

    var dbWriteTasks = clients.Select(c => DoSomeWorkAsync(c))
    var dbCollateTasks = clients.Select(c => DoSomeOtherWorkAsync(c));
    
    await Task.WhenAll(dbWriteTasks);
    await Task.WhenAll(dbCollateTasks);
    

    【讨论】:

    • 所有ToListToArray 调用都是多余的。如果你想简化代码,那不仅仅是重新排序那些顺序无关紧要的操作。
    • I'm attempting to run a collection of tasks, then once these have finished, run a separate collection of tasks 因为这个要求,我认为第一个await 应该移到var dbCollateTasks = ... 之前
    • @KevinGossek 纠正我,如果我错了,但 dbCollateTasks 不会运行,直到在第二个 WhenAll 中枚举延迟查询。
    • 哦,确实,我的错。不习惯看到 IEnumerable 和任务混在一起
    • 虽然如此,但像这样混淆代码并依赖 IEnumerable 延迟执行并不是一个好主意。为什么不在第一次等待之后移动整理任务初始化?
    猜你喜欢
    • 2018-08-22
    • 2011-03-28
    • 2021-11-27
    • 1970-01-01
    • 2018-04-03
    • 1970-01-01
    • 2014-08-05
    • 2021-12-13
    • 1970-01-01
    相关资源
    最近更新 更多