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

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