Parallel.ForEach不更新共享变量

时间:2016-10-04 19:50:15

标签: c# parallel-processing parallel.foreach

拥有以下代码,如何更新共享变量?

     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.

4 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:2)

改变你的代码,你会得到预期的结果:

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

答案 2 :(得分:0)

同样的原因它在“常规”C#代码中不起作用...整数是值类型,因此您需要使参数成为ref参数。否则,您只是递增本地副本。此外,您应该使用Interlocked.Increment而不是+ =,否则您可能遇到线程问题,因为+ =不一定是原子的。

答案 3 :(得分:0)

试试这个

int sum = list.AsParallel().Sum(person => person.Age);

结果将是相同的,将使用更少的代码。