考虑以下代码示例,它创建一个可枚举的整数集合并并行处理它:
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
的递增和返回的锁定机制?
最佳答案
Parallel.ForEach<TSource>
, 当 TSource
是一个 IEnumerable<T>
, 为 IEnumerable<T>
创建一个分区器它包含自己的内部锁定机制,因此您无需在迭代器中实现任何线程安全。
每当工作线程请求一大块项目时,分区程序将创建一个内部枚举器,它:
- 获取共享锁
- 遍历源(从它离开的地方)以检索项目 block ,将项目保存在私有(private)数组中
- 释放锁以便其他 block 请求可以得到满足。
- 从其私有(private)数组为工作线程提供服务。
如您所见,运行 IEnumerable<T>
出于分区的目的,分区是顺序的(通过共享锁访问),并且分区是并行处理的。
关于c# - 使用 Parallel.ForEach() 的 yield return 的线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17021779/