【发布时间】:2014-04-03 12:29:31
【问题描述】:
我有一个源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)。
【问题讨论】: