I'd like to use the power of Parallel.ForEach
on a List<T>
for a validation routine. The List is iterated to ensure a property is not < 1. A bool is created that is set to false if validation finds an error which is returned in the validation method call. I've been told that this code is problematic as bool is a primitive and not thread safe. Is there a way I can harness of the power of Parallel.ForEach
on a server with a lot of cores and RAM and ensure this works properly concerning thread safety?
我想在List
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;
}
2 个解决方案
#1
3
You can do that with PLINQ:
你可以用PLINQ做到这一点:
public static bool IsValid(List<Airport> entities)
{
return !entities.AsParallel().Any(entity => entity.UserId < 1);
}
However, since the part running in parallel is so small you'll get no improvement so you should stick with the regular foreach
(or LINQ):
但是,由于并行运行的部分非常小,所以你没有任何改进,所以你应该坚持使用常规的foreach(或LINQ):
public static bool IsValid(List<Airport> entities)
{
return !entities.Any(entity => entity.UserId < 1);
}
#2
1
If the list is big enough, I'd go with a PLINQ approach using Enumerable.Any
or Enumerable.All
:
如果列表足够大,我会使用Enumerable.Any或Enumerable.All来使用PLINQ方法:
return !entities.AsParallel().Any(x => x.UserId < 1);
Or
要么
return entities.AsParallel().All(x => !(x.UserId < 1));
Usually when a pipeline style execution is used, I find PLINQ more suitable than the Parallel
class as it removed the need to update a shared resource inside your parallel loop.
通常在使用管道样式执行时,我发现PLINQ比Parallel类更合适,因为它消除了更新并行循环内共享资源的需要。
Note you should benchmark your code to make sure parallelism is worth it. In many cases, if the list isn't big enough, this may de-grade performance.
请注意,您应该对代码进行基准测试,以确保并行性是值得的。在许多情况下,如果列表不够大,这可能会降低性能。
#1
3
You can do that with PLINQ:
你可以用PLINQ做到这一点:
public static bool IsValid(List<Airport> entities)
{
return !entities.AsParallel().Any(entity => entity.UserId < 1);
}
However, since the part running in parallel is so small you'll get no improvement so you should stick with the regular foreach
(or LINQ):
但是,由于并行运行的部分非常小,所以你没有任何改进,所以你应该坚持使用常规的foreach(或LINQ):
public static bool IsValid(List<Airport> entities)
{
return !entities.Any(entity => entity.UserId < 1);
}
#2
1
If the list is big enough, I'd go with a PLINQ approach using Enumerable.Any
or Enumerable.All
:
如果列表足够大,我会使用Enumerable.Any或Enumerable.All来使用PLINQ方法:
return !entities.AsParallel().Any(x => x.UserId < 1);
Or
要么
return entities.AsParallel().All(x => !(x.UserId < 1));
Usually when a pipeline style execution is used, I find PLINQ more suitable than the Parallel
class as it removed the need to update a shared resource inside your parallel loop.
通常在使用管道样式执行时,我发现PLINQ比Parallel类更合适,因为它消除了更新并行循环内共享资源的需要。
Note you should benchmark your code to make sure parallelism is worth it. In many cases, if the list isn't big enough, this may de-grade performance.
请注意,您应该对代码进行基准测试,以确保并行性是值得的。在许多情况下,如果列表不够大,这可能会降低性能。