C#并行-将项目添加到要迭代的集合中,还是等效? [英] C# Parallel - Adding items to the collection being iterated over, or equivalent?

查看:102
本文介绍了C#并行-将项目添加到要迭代的集合中,还是等效?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

现在,我有一个C#程序,该程序可以重复执行以下步骤:

Right now, I've got a C# program that performs the following steps on a recurring basis:

  • 从数据库中获取当前任务列表
  • 使用Parallel.ForEach()来完成每个任务

但是,其中一些任务的运行时间很长.这会延迟其他待处理任务的处理,因为我们仅在程序开始时寻找新任务.

However, some of these tasks are very long-running. This delays the processing of other pending tasks because we only look for new ones at the start of the program.

现在,我知道不可能修改要迭代的集合(对吗?),但是C#Parallel框架中有一些等效功能,可以使我向列表添加工作,同时还可以处理列表中的项目.列表吗?

Now, I know that modifying the collection being iterated over isn't possible (right?), but is there some equivalent functionality in the C# Parallel framework that would allow me to add work to the list while also processing items in the list?

推荐答案

通常来说,您是对的,不允许在迭代时修改集合.但是您可能会使用其他方法:

Generally speaking, you're right that modifying a collection while iterating it is not allowed. But there are other approaches you could be using:

  • Use ActionBlock<T> from TPL Dataflow. The code could look something like:

var actionBlock = new ActionBlock<MyTask>(
    task => DoWorkForTask(task),
    new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded });

while (true)
{
    var tasks = GrabCurrentListOfTasks();
    foreach (var task in tasks)
    {
        actionBlock.Post(task);

        await Task.Delay(someShortDelay);
        // or use Thread.Sleep() if you don't want to use async
    }
}

  • 使用 BlockingCollection<T> ,在使用时可以对其进行修改以及来自ParallelExtensionsExtras的 GetConsumingParititioner() a>使其与Parallel.ForEach()一起使用:

  • Use BlockingCollection<T>, which can be modified while consuming items from it, along with GetConsumingParititioner() from ParallelExtensionsExtras to make it work with Parallel.ForEach():

    var collection = new BlockingCollection<MyTask>();
    
    Task.Run(async () =>
    {
        while (true)
        {
            var tasks = GrabCurrentListOfTasks();
            foreach (var task in tasks)
            {
                collection.Add(task);
    
                await Task.Delay(someShortDelay);
            }
        }
    });
    
    Parallel.ForEach(collection.GetConsumingPartitioner(), task => DoWorkForTask(task));
    

  • 这篇关于C#并行-将项目添加到要迭代的集合中,还是等效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆