【问题标题】:Running groups of groups of Tasks in a For loop在 For 循环中运行任务组
【发布时间】:2019-08-10 02:56:59
【问题描述】:

我有一组 100 个任务需要按任意顺序运行。将它们全部放入 Task.WhenAll() 往往会使后端超载,而我无法控制。

我想一次运行 n 个任务,每次完成后,再运行下一组。我写了这段代码,但是在任务运行之后,“控制台(正在运行...”)被打印到屏幕上,这让我觉得所有的任务都在运行。

如何强制系统真正“等待”每组任务?

//Run some X at a time
int howManytoRunAtATimeSoWeDontOverload = 4;
for(int i = 0; i < tasks.Count; i++)
{
    var startIndex = howManytoRunAtATimeSoWeDontOverload * i;
    Console.WriteLine($"Running {startIndex} to {startIndex+ howManytoRunAtATimeSoWeDontOverload}");

    var toDo = tasks.Skip(startIndex).Take(howManytoRunAtATimeSoWeDontOverload).ToArray();
    if (toDo.Length == 0) break;
    await Task.WhenAll(toDo);
}

屏幕输出:

【问题讨论】:

  • 您有 100 个任务正在运行,但您不知道它们将按什么顺序完成。 WhenAll 不会启动任务,它只是等待它们完成。听起来您真正想要的是限制启动。分组开始并等待该组完成,然后再开始下一组。

标签: c# for-loop async-await


【解决方案1】:

有很多方法可以做到这一点,但我可能会使用一些提供更高级别抽象的库或框架,例如 TPL 数据流:https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/dataflow-task-parallel-library(如果您使用 .NET Core,则有更新的库)。

这比构建自己的缓冲机制要容易得多。下面是一个非常简单的示例,但您可以对它进行不同的配置,并使用这个库做更多的事情。在下面的示例中,我没有对它们进行批处理,但我确保同时处理的任务不超过 10 个。

        var buffer = new ActionBlock<Task>(async t =>
        {
            await t;
        }, new ExecutionDataflowBlockOptions { BoundedCapacity = 10, MaxDegreeOfParallelism = 1 });

        foreach (var t in tasks)
        {
            await buffer.SendAsync(DummyFunctionAsync(t));
        }

        buffer.Complete();
        await buffer.Completion;

【讨论】:

  • 赞成,但改变了我的想法。 foreach (var t in tasks) 表示有一个任务列表已经开始,并且您的代码只是分批等待它们,与一个接一个或一次等待它们相比没有真正的区别。也许您打算写foreach (var i in items),但在这种情况下,在动作中创建任务并使用MaxDegreeOfParallelism (example) 进行限制比在SendAsync 期间创建任务并使用@987654328 进行限制更有意义@.
  • @TheodorZoulias:你有一个有效的观点,但我对原始问题中任务的来源(线程池或一些 IO 操作)知之甚少。所以我决定用这个例子。我的主要观点是,他应该寻找一些更高级别的抽象,比如 TPL Dataflow 提供的抽象。
  • 老实说,您的示例确保任务将按顺序创建(假设 DummyFunctionAsync 是任务工厂函数),这在某些情况下可能是可取的。将任务创建移动到操作中将导致任务同时创建,从而引发对DummyFunctionAsync 内部线程安全的担忧。所以你的代码可能更可取。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-04
  • 2020-03-01
相关资源
最近更新 更多