C# 并发执行有限数量的任务

C# 并发执行有限数量的任务,c#,concurrency,task,C#,Concurrency,Task,假设我有一个IEnumerable来生成一些我想要并发执行的(爬虫)任务,我如何设置并发的上限 例如,我不希望这些任务中有超过5个同时运行。另一方面,如果可能,应该始终有5个任务在运行 我目前的做法是这样的: public static async Task ExecuteConcurrent(IEnumerable<Func<Task>> taskGenerators, int maxDegreeOfConcurrency) { var

假设我有一个
IEnumerable
来生成一些我想要并发执行的(爬虫)任务,我如何设置并发的上限

例如,我不希望这些任务中有超过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);
    }
公共静态异步任务ExecuteConcurrent(IEnumerable taskGenerators,int-maxDegreeOfConcurrency)
{
var executingTasks=new HashSet();
foreach(taskGenerators中的var taskGenerator){
while(executingTasks.Count>=maxDegreeOfConcurrency){
executingTasks.Remove(wait Task.wheny(executingTasks));
}
添加(taskGenerator());
}
等待任务。何时(执行任务);
}
我想知道是否有更好的方法来做到这一点?也许,已经有一种方法可用

谢谢你

听起来像是一份适合你的工作

优点是:

  • 它适用于
    async
    await
    以及CPU绑定和IO绑定的工作负载
  • 您可以使用
    MaxDegreeOfParallelism
    和许多其他选项限制并发
  • 您可以将其链接到更复杂的管道中
  • 适用于被动扩展
  • 这都是Stephen Toub先生为你打造的

  • 非常基本的示例

    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
    }
    
    公共静态异步任务工作负载(列表地址)
    {
    var options=新的ExecutionDataflowBlockOptions
    {
    MaxDegreeOfParallelism=50//此处限制
    };
    var block=新操作块(MyMethodAsync,选项);
    foreach(地址中的var ip)
    区块邮政(ip);
    block.Complete();
    等待区块完成;
    }
    ...
    公共异步任务MyMethodAsync(SomeObject obj)
    {
    //在这里等着什么
    }
    
    Cool solution:)!谢谢:)!如果我的
    IEnumerable
    很大(=比我的内存大),该怎么办。在此解决方案中,将尽快使用完整的
    IEnumerable
    (如果我们将
    List
    替换为
    IEnumerable
    )。这可以避免或减少吗?是的,有很多选择,这是为复杂和苛刻的工作负载而设计的。可能会在第三方物流数据流上查找Stephen toubs播客,尽管他们看起来有点像bgrade,但他会涵盖很多我在我的网站上看不到的东西phone@KevinMeier:您需要为此设置
    BoundedCapacity
    选项。