【问题标题】:Are those Lists safe thread in Parallel.For?这些列表是 Parallel.For 中的安全线程吗?
【发布时间】:2023-04-04 01:30:01
【问题描述】:

我必须从 Parallel.ForEach 中删除 lock 对象。我应该使用ConcurrentBag 还是直接删除它?如果没有 lock 对象,它是线程安全的吗?

resultsList<>

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;
            }
        }
    }
});

【问题讨论】:

    标签: c# multithreading parallel-processing thread-safety parallel.foreach


    【解决方案1】:

    我假设您提供的代码使用重载,该重载采用 localInit 值并分别使用 localFinally Func&lt;T&gt;Action&lt;T&gt;,如下所示:

    public static ParallelLoopResult ForEach<TSource, TLocal>(
        IEnumerable<TSource> source,
        ParallelOptions parallelOptions,
        Func<TLocal> localInit,
        Func<TSource, ParallelLoopState, TLocal, TLocal> body,
        Action<TLocal> localFinally
    )
    

    仍然是强制性的,因为最终操作必须将项目并行添加到基础列表中。您可以使用ConcurrentBag&lt;T&gt; 进行最终连接,但我建议您对这两种方法进行基准测试,看看哪种方法的性能更高。

    也许更适合您的另一种方法是使用PLINQ。这样,您可以并行操作多个项目,并且仅在最后使用 ToList 来创建包含您的结果的 List&lt;T&gt;

    var result = entityList.AsParallel()
                           .Select(childObject => 
                                    currentChildrenManager.Prepare(
                            childObject, currentAnalyticalDataHolder, out childrenAllData))
                           .ToList();
    // Modify the list further if needed.
    

    【讨论】:

      猜你喜欢
      • 2020-05-02
      • 1970-01-01
      • 2015-08-11
      • 2011-09-13
      • 1970-01-01
      • 2021-09-23
      • 2015-10-13
      • 1970-01-01
      相关资源
      最近更新 更多