Parallel.ForEach 和全局变量
Parallel.ForEach and global variable
如果我有如下代码:
var dict = new Dictionary<string, NetObject>();
Parallel.ForEach(results, options, result =>
{
var items = parser.Parse(result);
Parallel.ForEach(items, options, nextObject =>
{
if (nextObject != null)
{
dict[nextObject.Id] = nextObject;
}
});
});
dict 是在方法级别定义的字典。我的问题是,它是否会导致并行 foreach 以同步方式像普通 foreach 一样工作,因为它是全局对象?对于上面的代码,我没有看到正常的 foreach 和 parallel once 之间有任何性能差异。
您的代码不是线程安全的。您正在改变 Dictionary<K, V>
这不是线程安全的数据结构。此外,您很可能将循环与 Parallel.ForEach
过度并行化以迭代内部和外部循环。
让我推荐一种使用 PLINQ 的不同方法,它不需要您同步全局 Dictionary
。请注意,执行此操作时应确保没有重复键(可能需要额外的 .Distinct()
调用):
results
.AsParallel()
.SelectMany(x => parser.Parse(x))
.Where(x => x != null)
.ToDictionary(x => x.Id, x => x);
当然,最重要的是对您的代码进行基准测试,以确保并行性确实提高了性能,并且您可以从中获益。
如果我有如下代码:
var dict = new Dictionary<string, NetObject>();
Parallel.ForEach(results, options, result =>
{
var items = parser.Parse(result);
Parallel.ForEach(items, options, nextObject =>
{
if (nextObject != null)
{
dict[nextObject.Id] = nextObject;
}
});
});
dict 是在方法级别定义的字典。我的问题是,它是否会导致并行 foreach 以同步方式像普通 foreach 一样工作,因为它是全局对象?对于上面的代码,我没有看到正常的 foreach 和 parallel once 之间有任何性能差异。
您的代码不是线程安全的。您正在改变 Dictionary<K, V>
这不是线程安全的数据结构。此外,您很可能将循环与 Parallel.ForEach
过度并行化以迭代内部和外部循环。
让我推荐一种使用 PLINQ 的不同方法,它不需要您同步全局 Dictionary
。请注意,执行此操作时应确保没有重复键(可能需要额外的 .Distinct()
调用):
results
.AsParallel()
.SelectMany(x => parser.Parse(x))
.Where(x => x != null)
.ToDictionary(x => x.Id, x => x);
当然,最重要的是对您的代码进行基准测试,以确保并行性确实提高了性能,并且您可以从中获益。