我有一个源IEnumerable<T>
,我希望以并行方式处理,具有固定数量的任务/线程(接近处理器数量),每个任务/线程从源和进程中获取下一个项目直到所有元素都被迭代完毕。
Parallel.For
不是候选者。Parallel.ForEach
不是候选者,因为即使在指定MaxDegreeOfParallelism
时也创建了许多任务,因为此参数仅确保并发运行的最大任务数,而不是创建的任务数。听起来像生产者/消费者的问题,生产者可以是单线程的简化,一旦IEnumerable完成,就不会再添加元素了。
这个问题的解决方案如何使用TPL?我是否必须实现自己的可共享线程安全IEnumerable
或框架是否提供了什么?
编辑:这是我尝试使用Parallel.ForEach
并指定MaxDegreeOfParallelism
,这不会阻止TPL创建许多任务。
int nbTasks = 0;
Parallel.ForEach(positions, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount },
() => { return new List<IPositionData>(); },
(position, loop, list) =>
{
Thread.Sleep(1);
list.Add(position);
return list;
},
list => Interlocked.Add(ref nbTasks, 1));
Trace.WriteLine(string.Format("Tasks: {0}", nbTasks));
评论:positions
是我的来源IEnumerable<IPositionData>
。我刚刚运行了这个,例如,nbTasks是64(而不是我4核上预期的4个)。
答案 0 :(得分:6)
您可以使用需要Parallel.ForEach
对象并设置ParallelOptions
属性的重载来限制MaxDegreeOfParallelism
中的任务数。
答案 1 :(得分:0)
您可以在Parallel.ForEach
中限制任务数量:
in maxNumberOfTasks = 4;
Parallel.ForEach(collection, new ParallelOptions { MaxDegreeOfParallelism = maxNumberOfTasks},
i => {
//Your action here
});