问题描述
现在,我有一个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:
-
使用TPL Dataflow中的
ActionBlock<T>
.该代码可能类似于:
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()
一起使用:
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#并行-将项目添加到要迭代的集合中,还是等效?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!