我必须从Parallel.ForEach
删除 lock 对象。我应该使用ConcurrentBag
还是删除它?没有 lock 对象,它是否是线程安全的?
results
是List<>
。
Parallel.ForEach(entityList, options,
() =>
{
List<Customer> childrenResult = new List<Customer>();
return childrenResult;
},
(childrenObject, loopState, childrenResult) =>
{
childrenResult.AddRange(currentChildrenManager.Prepare(childrenObject, currentAnalyticalDataHolder, () => loopState.IsStopped, out childrenAllData));
return childrenResult;
},
(childrenResult) =>
{
lock (lockingObject)
{
if (childrenResult == null)
results.AddRange(new List<Customer>());
else if (currentChildrenManager.RowOrFilteredRowLimitation == null)
results.AddRange(childrenResult);
else
{
int leftCount = currentChildrenManager.RowOrFilteredRowLimitation.GetRelativRowLimitation(provider.IsForGenerationTime) - results.Count();
if (leftCount > 0)
{
if (childrenResult.Count() > leftCount)
{
tAllData = currentChildrenManager.OnlyFirst;
results.AddRange(childrenResult.Take(leftCount));
}
else
results.AddRange(childrenResult);
}
else
{
tAllData = currentChildrenManager.OnlyFirst;
}
}
}
});
答案 0 :(得分:1)
我假设您提供的代码使用了一个带有protected
值的重载,并分别使用localInit
localFinally
和Func<T>
看起来像这样:
Action<T>
锁仍然是强制性的,因为最终操作必须并行地将项目添加到基础列表。您可以使用public static ParallelLoopResult ForEach<TSource, TLocal>(
IEnumerable<TSource> source,
ParallelOptions parallelOptions,
Func<TLocal> localInit,
Func<TSource, ParallelLoopState, TLocal, TLocal> body,
Action<TLocal> localFinally
)
进行最后的连接,但我建议您使用这两种方法进行基准测试,以确定哪种方式可以获得更高效的结果。
或许可能更适合您的不同方法是使用PLINQ。这样,您可以并行处理多个项目,最后只使用ConcurrentBag<T>
创建包含结果的ToList
:
List<T>