C# 与固定数量的任务/线程并行使用IEnumerable
我有一个源C# 与固定数量的任务/线程并行使用IEnumerable,c#,task-parallel-library,C#,Task Parallel Library,我有一个源IEnumerable,我想以并行方式处理它,有固定数量的任务/线程(接近处理器的数量),每个任务/线程从源抓取下一个项目并处理它,直到所有元素都被迭代 Parallel.For不是候选项,因为元素的数量未知 Parallel.ForEach不是候选项,因为即使指定了maxdegreeofpparallelism,is也会创建许多任务,因为此参数仅确保并发运行的最大任务数,而不确保创建的任务数 必须通知每个任务,源代码一直被遍历到其结束,以便它可以运行一些包装逻辑 源列表的元素不能保
IEnumerable
,我想以并行方式处理它,有固定数量的任务/线程(接近处理器的数量),每个任务/线程从源抓取下一个项目并处理它,直到所有元素都被迭代
不是候选项,因为元素的数量未知Parallel.For
不是候选项,因为即使指定了Parallel.ForEach
,is也会创建许多任务,因为此参数仅确保并发运行的最大任务数,而不确保创建的任务数maxdegreeofpparallelism
- 必须通知每个任务,源代码一直被遍历到其结束,以便它可以运行一些包装逻辑
- 源列表的元素不能保存在内存中,但必须连续处理和丢弃
IEnumerable
,还是框架提供了什么
编辑:这是我尝试使用Parallel.ForEach
并指定maxdegreeofpparallelism
,这不会阻止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));
int nbTasks=0;
ForEach(位置,新的并行选项{MaxDegreeOfParallelism=Environment.ProcessorCount},
()=>{返回新列表();},
(位置、循环、列表)=>
{
睡眠(1);
列表。添加(位置);
退货清单;
},
list=>Interlocked.Add(参考nbTasks,1));
WriteLine(string.Format(“Tasks:{0}”,nbTasks));
注释:
positions
是我的源代码IEnumerable
。我刚刚运行了这个,例如,nbTasks是64(而不是我的4核上预期的4).您可以通过使用期望ParallelOptions
对象的重载并设置MaxDegreeOfParallelism
属性来限制Parallel.ForEach
中的任务数。您可以通过使用期望ParallelOptions
的重载来限制Parallel.ForEach中的任务数对象并设置MaxDegreeOfParallelism
属性。您可以限制并行中的任务数。ForEach
:
in maxNumberOfTasks = 4;
Parallel.ForEach(collection, new ParallelOptions { MaxDegreeOfParallelism = maxNumberOfTasks},
i => {
//Your action here
});
您可以限制并行中的任务数。ForEach
:
in maxNumberOfTasks = 4;
Parallel.ForEach(collection, new ParallelOptions { MaxDegreeOfParallelism = maxNumberOfTasks},
i => {
//Your action here
});
我已经尝试过了,但没有成功。尽管我将MaxDegreeOfParallelism指定给示例4,但创建的任务比示例4多得多。我猜,这是由于初始化,这不是唯一的CPU限制。我编辑了我的问题以反映这一点。@Dejan你能给我们看一下你的代码吗?我刚刚尝试了一个简单的例子,我可以验证在我的例子中,MaxDegreeOfParallelism
是否正确工作。@Dejan我看到了你的问题MaxDegreeOfParallelism
只确保并发任务的数量不超过您的总数,而不限制创建的任务数量。您是否可以修改localInit
lambda,以便在后续任务之间重用复杂初始化的结果?您最多需要执行Environment.ProcessorCount
初始化。如果没有,您可能需要编写自己的TaskScheduler
。或者,请使用parallel.For
,但不是根据项目的数量,而是根据要创建的并发任务的数量。然后您只需要同步对枚举器的访问。啊,这是一个很好的了解-现在我理解了MaxDegreeOfParallelism
,谢谢。但总而言之,这又回到了我最初的问题。我是否必须实现我的单同步枚举器或自定义调度程序,或者框架是否提供了一些开箱即用的内容来覆盖我的场景。尽管我将MaxDegreeOfParallelism指定给示例4,但创建的任务比示例4多得多。我猜,这是由于初始化,这不是唯一的CPU限制。我编辑了我的问题以反映这一点。@Dejan你能给我们看一下你的代码吗?我刚刚尝试了一个简单的例子,我可以验证在我的例子中,MaxDegreeOfParallelism
是否正确工作。@Dejan我看到了你的问题MaxDegreeOfParallelism
只确保并发任务的数量不超过您的总数,而不限制创建的任务数量。您是否可以修改localInit
lambda,以便在后续任务之间重用复杂初始化的结果?您最多需要执行Environment.ProcessorCount
初始化。如果没有,您可能需要编写自己的TaskScheduler
。或者,请使用parallel.For
,但不是根据项目的数量,而是根据要创建的并发任务的数量。然后您只需要同步对枚举器的访问。啊,这是一个很好的了解-现在我理解了MaxDegreeOfParallelism
,谢谢。但总而言之,这又回到了我最初的问题。我是否必须实现我的单同步枚举器或自定义调度程序,或者框架是否提供了一些开箱即用的内容来覆盖我的场景。