与固定数量的任务/线程并行使用IEnumerable

时间:2014-04-03 12:29:31

标签: c# task-parallel-library

我有一个源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个)。

2 个答案:

答案 0 :(得分:6)

您可以使用需要Parallel.ForEach对象并设置ParallelOptions属性的重载来限制MaxDegreeOfParallelism中的任务数。

答案 1 :(得分:0)

您可以在Parallel.ForEach中限制任务数量:

   in maxNumberOfTasks = 4;
   Parallel.ForEach(collection, new ParallelOptions { MaxDegreeOfParallelism = maxNumberOfTasks}, 
                 i => {
                        //Your action here
                  });