Parallel.For() 更新项目的属性

Parallel.For() updating properties of an item

假设我有一个 "distinct" 需要更新的人员列表。我想使用 Parallel.For()

有问题的方法:

public void UpdatePerson(Person row){
   row.Name = //get from cache and update property
}

VS

public Person UpdatePerson(Person row){
   row.Name = //get from cache and update property
   return row;
}

当使用 Parallel.For() 枚举此列表并 运行 这些并行更新(即调用此方法)时,使用一个与另一个相比是否存在任何潜在问题?

让我们暂时离开平行部分,你想要做的是对人员列表中的项目进行一些操作,你会选择为此目的使用循环:

for(int i = 0; i < persons.Length, i++)
{
    persons[i].Name = "SomeName;
}

或者foreach循环:

foreach(Person person in persons)
{
    person.Name = "SomeName";
}

我更喜欢在这种情况下使用 foreach 循环,因为我发现它更合适和清晰,在我看来这是一个显而易见的选择。

现在让我们回到并行部分,Parallel.For() should be used to execute for loops in parallel while Parallel.Foreach() 应该用于并行执行 foreach 循环。
因此,如果我们同意 foreach 循环在这种情况下更合适,那么我们也应该更喜欢 Parallel.Foreach() 而不是 Parallel.For()。

现在对于你的问题 Parallel.Foreach() 将采用 T 的 Action 作为参数,因此如果你想将方法名称传递给操作,它必须是 void 方法,因为 Action of T 是一个 void 的委托获取类型 T 的一个参数的方法。

因此,使用您的第一种方法应该可行:

public void UpdatePersonName(Person person)
{
    person.Name = "SomeName";
}

和并行部分(使用this重载):

Parallel.Foreach(persons, UpdatePersonName);

另一种替代创建单独方法的方法是使用 lambda 表达式:

Parallel.Foreach(persons, person => person.Name = "SomeName" );

由于这个原因,您不能使用第二种方法:

public Person UpdatePersonName(Person person)
{
   person.Name = "SomeName";
   return person;
}

在 Parallel.Foreach() 内部,因为它的 return 类型不是 void。

另一件你应该知道的重要事情,如果你正在使用 Parallel.Foreach() ,你将需要确保线程安全,并且大多数时候你需要使用某种锁定来实现这一点。
你应该仔细考虑这一点,因为有时它不值得开销,在某些情况下 foreach loops can run faster than their parallel equivalents.