现在,我有一个 C# 程序可以重复执行以下步骤:
- 从数据库中获取当前任务列表
- 使用 Parallel.ForEach(),为每个任务做工作
但是,其中一些任务运行时间非常长。这会延迟其他挂起任务的处理,因为我们只在程序开始时寻找新任务。
现在,我知道修改正在迭代的集合是不可能的(对吗?),但是 C# Parallel 框架中是否有一些等效的功能允许我向列表添加工作,同时处理名单?
最佳答案
一般来说,您是对的,在迭代集合时修改集合是不允许的。但是您还可以使用其他方法:
使用
ActionBlock<T>
from TPL Dataflow .代码可能类似于: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>
,可以在消耗其中的项目时修改它,以及GetConsumingParititioner()
from ParallelExtensionsExtras使其与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# Parallel - 将项目添加到正在迭代的集合中,或等效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33659380/