考虑以下代码示例,它创建一个可枚举的整数集合并并行处理它:
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
Parallel.ForEach(CreateItems(100), item => ProcessItem(item));
}
private static IEnumerable<int> CreateItems(int count)
{
for (int i = 0; i < count; i++)
{
yield return i;
}
}
private static void ProcessItem(int item)
{
// Do something
}
}
是否保证Parallel.ForEach()
生成的工作线程每个都获得一个不同的项目,或者是否需要一些锁定机制来增加和返回i
?
答案 0 :(得分:11)
Parallel.ForEach<TSource>
为TSource
时, IEnumerable<T>
会为IEnumerable<T>
创建一个包含其自己的内部锁定机制的分区程序,因此您不需要在迭代器中实现任何线程安全性。
每当工作线程请求一大块项目时,分区程序将创建一个内部枚举器,其中:
如您所见,为了分区而运行IEnumerable<T>
是顺序的(通过共享锁访问),并且并行处理分区。
答案 1 :(得分:2)
TPL和PLINQ使用 partitioners 的概念。
分区程序是一种类型,它继承Partitioner<TSource>
并用于将源序列拆分为多个部分(或分区)。内置分区器旨在将源序列拆分为非重叠分区。