【问题标题】:Using Parallel.ForEach<T> to set a bool external to Parallel.ForEach使用 Parallel.ForEach<T> 设置 Parallel.ForEach 外部的布尔值
【发布时间】:2015-07-04 18:45:38
【问题描述】:

我想在List&lt;T&gt; 上使用Parallel.ForEach 的强大功能来进行验证例程。迭代列表以确保属性不 Parallel.ForEach 的强大功能,并确保它在线程安全方面正常工作?

public static bool IsValid(List<Airport> entities)
{
    bool isValid = true;

    Parallel.ForEach<Airport>(entities, entity =>
    {
        // userId can't be less than 1
        if (entity.userId < 1)
        {
            SiAuto.Main.LogMessage("Airport {0}: invalid userId {1}", entity.airportId, entity.userId);
            isValid = false;
            System.Diagnostics.Debugger.Break();
        }
    });

    return isValid;
}

【问题讨论】:

  • 由于您只将其设置为 false,我不明白这不是线程安全的。
  • 但是你不想在第一个错误之后就中断循环吗?
  • 列表有多大?
  • 我不明白同步问题..这里不是线程安全的..某些线程可能将其设置为假..那又怎样?

标签: c# .net multithreading parallel-processing task-parallel-library


【解决方案1】:

您可以使用 PLINQ 做到这一点:

public static bool IsValid(List<Airport> entities)
{
    return !entities.AsParallel().Any(entity => entity.UserId < 1);
}

但是,由于并行运行的部分非常小,您不会得到任何改进,因此您应该坚持使用常规的 foreach(或 LINQ):

public static bool IsValid(List<Airport> entities)
{
    return !entities.Any(entity => entity.UserId < 1);
}

【讨论】:

    【解决方案2】:

    如果列表足够大,我会使用 Enumerable.AnyEnumerable.All 的 PLINQ 方法:

    return !entities.AsParallel().Any(x => x.UserId < 1);
    

    或者

    return entities.AsParallel().All(x => !(x.UserId < 1));
    

    通常在使用管道式执行时,我发现 PLINQ 比 Parallel 类更合适,因为它无需更新并行循环内的共享资源。

    请注意,您应该对代码进行基准测试,以确保并行性是值得的。在许多情况下,如果列表不够大,可能会降低性能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-16
      • 2021-03-20
      • 1970-01-01
      • 1970-01-01
      • 2014-04-11
      • 1970-01-01
      相关资源
      最近更新 更多