Parallel.ForEach 不更新共享变量
Parallel.ForEach does not update shared variable
有如下代码,如何更新共享变量?
List<Person> list = new List<Person> {new Person {Age = 1}, new Person {Age = 2}, new Person {Age = 5}};
long total = 0;
Parallel.ForEach(list, () => 0, (person, loop, subtotal) =>
{
Add(person, subtotal);
return subtotal;
},
finalResult => Interlocked.Add(ref total, finalResult)
);
public static void Add(Person person, int shared)
{
// Do some work
shared =+ person.Age;
}
出于某种原因,共享返回为 0。
同样的原因,它在 "regular" C# 代码中不起作用...整数是值类型,因此您需要将参数设为 ref 参数。否则,您只是在增加本地副本。此外,您应该使用 Interlocked.Increment 而不是 +=,否则您可能 运行 会陷入线程问题,因为 += 不一定是原子的。
Shared 返回为 0,因为它作为 0 发送并按值传递。您需要使用 ref 关键字,或以其他方式(静态变量)解决此问题。
public static void Add(Person person, ref int shared)
{
// Do some work
shared =+ person.Age;
}
您似乎也遇到了使用“= +”代替“+=”的问题。
public static void Add(Person person, ref int shared)
{
// You likely meant to do this.
shared += person.Age;
}
稍微更改一下您的代码,您将获得预期的结果:
static void Main(string[] args)
{
List<Person> persons = new List<Person>
{
new Person { Age = 1 },
new Person { Age = 2 },
new Person { Age = 5 }
};
long total = 0;
Parallel.ForEach(persons, person => Add(person, ref total));
Console.WriteLine(total);
Console.ReadKey();
}
public static void Add(Person person, ref long shared)
{
// since here you access a shared variabe, we
// can use the Interlocked class in order our operation
// to be atomic.
Interlocked.Add(ref shared, person.Age);
}
试试这个
int sum = list.AsParallel().Sum(person => person.Age);
结果将是相同的,并且将使用更少的代码。
有如下代码,如何更新共享变量?
List<Person> list = new List<Person> {new Person {Age = 1}, new Person {Age = 2}, new Person {Age = 5}};
long total = 0;
Parallel.ForEach(list, () => 0, (person, loop, subtotal) =>
{
Add(person, subtotal);
return subtotal;
},
finalResult => Interlocked.Add(ref total, finalResult)
);
public static void Add(Person person, int shared)
{
// Do some work
shared =+ person.Age;
}
出于某种原因,共享返回为 0。
同样的原因,它在 "regular" C# 代码中不起作用...整数是值类型,因此您需要将参数设为 ref 参数。否则,您只是在增加本地副本。此外,您应该使用 Interlocked.Increment 而不是 +=,否则您可能 运行 会陷入线程问题,因为 += 不一定是原子的。
Shared 返回为 0,因为它作为 0 发送并按值传递。您需要使用 ref 关键字,或以其他方式(静态变量)解决此问题。
public static void Add(Person person, ref int shared)
{
// Do some work
shared =+ person.Age;
}
您似乎也遇到了使用“= +”代替“+=”的问题。
public static void Add(Person person, ref int shared)
{
// You likely meant to do this.
shared += person.Age;
}
稍微更改一下您的代码,您将获得预期的结果:
static void Main(string[] args)
{
List<Person> persons = new List<Person>
{
new Person { Age = 1 },
new Person { Age = 2 },
new Person { Age = 5 }
};
long total = 0;
Parallel.ForEach(persons, person => Add(person, ref total));
Console.WriteLine(total);
Console.ReadKey();
}
public static void Add(Person person, ref long shared)
{
// since here you access a shared variabe, we
// can use the Interlocked class in order our operation
// to be atomic.
Interlocked.Add(ref shared, person.Age);
}
试试这个
int sum = list.AsParallel().Sum(person => person.Age);
结果将是相同的,并且将使用更少的代码。