【问题标题】:Execute a limited number of Tasks concurrent并发执行有限数量的任务
【发布时间】:2019-02-22 06:53:16
【问题描述】:

鉴于我有一个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);
    }

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

谢谢

【问题讨论】:

    标签: c# concurrency task


    【解决方案1】:

    听起来像是TPL Dataflow 的工作

    优点是:

    1. 它适用于 asyncawait 以及 CPU 限制IO 限制 工作负载
    2. 您可以使用MaxDegreeOfParallelism 和许多其他选项来限制并发
    3. 您可以将其链接成更复杂的管道
    4. 反应式扩展配合得很好
    5. 这一切都是由 Parallel 先生为您打造的Stephen Toub

    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
    }
    

    【讨论】:

    • 很酷的解决方案:)!谢谢:)!如果我的IEnumerable 很大(=比我的记忆还大)怎么办。在此解决方案中,完整的IEnumerable(如果我们将List&lt;IPAddress&gt; 替换为IEnumerable&lt;T&gt;)将尽快被使用。这可以避免或减少吗?因为它真的没有必要。
    • 是的,有很多选择,这是专为复杂和苛刻的工作负载而设计的。可能会在 tpl 数据流上查找 Stephen toubs 播客,虽然它们看起来有点高级,但他会涵盖很多我在手机上无法做到的事情
    • @KevinMeier:您需要为此设置BoundedCapacity 选项。
    猜你喜欢
    • 2022-10-15
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-08
    • 1970-01-01
    相关资源
    最近更新 更多