并发执行有限数量的任务

时间:2019-02-22 06:53:16

标签: c# concurrency task

鉴于我有一个IEnumerable<Func<Task>>来生成一些我想同时执行的(抓取)任务,如何为并发设置上限?

例如,我不希望同时运行5个以上的任务。另一方面,如果可能的话,总是应该有5个任务在运行。

我当前的方法是这段代码:

    public static async Task ExecuteConcurrent(IEnumerable<Func<Task>> taskGenerators, int maxDegreeOfConcurrency)
    {
        var executingTasks = new HashSet<Task>();
        foreach (var taskGenerator in taskGenerators) {
            while (executingTasks.Count >= maxDegreeOfConcurrency) {
                executingTasks.Remove(await Task.WhenAny(executingTasks));
            }

            executingTasks.Add(taskGenerator());
        }

        await Task.WhenAll(executingTasks);
    }

我想知道是否有更好的方法可以做到这一点?也许已经有一种方法可用了?

谢谢

1 个答案:

答案 0 :(得分:2)

听起来像TPL Dataflow的工作

优点是:

  1. 它与asyncawait以及 CPU约束 IO约束工作负载都很好地工作
  2. 您可以使用MaxDegreeOfParallelism和许多其他选项来限制并发性
  3. 您可以链接到更复杂的 PipeLines
  4. 反应性扩展
  5. 配合使用
  6. 所有这些都是Parallel先生 Stephen Toub
  7. 为您建造的

Nuget System.Threading.Tasks.Dataflow


非常基本的示例

public static async Task DoWorkLoads(List<IPAddress> addresses)
{
   var options = new ExecutionDataflowBlockOptions
                     {
                        MaxDegreeOfParallelism = 50 // limit here
                     };

   var block = new ActionBlock<SomeObject>(MyMethodAsync, options);

   foreach (var ip in addresses)
      block.Post(ip);

   block.Complete();
   await block.Completion;

}

...

public async Task MyMethodAsync(SomeObject obj)
{
    // await something here
}