C# Parallel.ForEach不更新共享变量
有了下面的代码,我如何更新共享变量C# Parallel.ForEach不更新共享变量,c#,parallel-processing,parallel.foreach,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) =>
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;
}
List List=newlist{new Person{Age=1},new Person{Age=2},new Person{Age=5};
长总计=0;
Parallel.ForEach(list,()=>0,(person,loop,subtotal)=>
{
加(人,小计);
返回小计;
},
finalResult=>Interlocked.Add(参考总计,finalResult)
);
公共静态无效添加(个人,整数共享)
{
//做些工作
共享=+个人年龄;
}
出于某种原因,shared返回为0 同样的原因,它在“常规”C#代码中不起作用。。。整数是值类型,因此需要将参数设置为ref参数。否则,您只是增加本地副本。另外,您应该使用Interlocked.Increment而不是+=,否则您可能会遇到线程问题,因为+=不一定是原子的。同样的原因,它在“常规”C#代码中不起作用。。。整数是值类型,因此需要将参数设置为ref参数。否则,您只是增加本地副本。另外,您应该使用Interlocked.Increment而不是+=,否则您可能会遇到线程问题,因为+=不一定是原子的。共享返回为0,因为它作为0发送,并通过值传递。您需要使用关键字,或者以其他方式解决此行为(静态变量) 看起来您在使用'=+'代替'+='时也遇到了问题
public static void Add(Person person, ref int shared)
{
// You likely meant to do this.
shared += person.Age;
}
Shared返回为0,因为它以0的形式发送,并通过值传递。您需要使用关键字,或者以其他方式解决此行为(静态变量) 看起来您在使用'=+'代替'+='时也遇到了问题
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);
}
static void Main(字符串[]args)
{
名单人员=新名单
{
新人{Age=1},
新人{Age=2},
新人{年龄=5}
};
长总计=0;
Parallel.ForEach(persons,person=>Add(person,ref-total));
控制台写入线(总计);
Console.ReadKey();
}
公共静态无效添加(个人,参考长期共享)
{
//既然您在这里访问共享变量,我们
//可以使用联锁类来进行我们的操作
//是原子的。
联锁。添加(参考共享,人。年龄);
}
稍微更改一下您的代码,您将获得预期的结果:
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);
}
static void Main(字符串[]args)
{
名单人员=新名单
{
新人{Age=1},
新人{Age=2},
新人{年龄=5}
};
长总计=0;
Parallel.ForEach(persons,person=>Add(person,ref-total));
控制台写入线(总计);
Console.ReadKey();
}
公共静态无效添加(个人,参考长期共享)
{
//既然您在这里访问共享变量,我们
//可以使用联锁类来进行我们的操作
//是原子的。
联锁。添加(参考共享,人。年龄);
}
试试这个
int sum = list.AsParallel().Sum(person => person.Age);
结果将是相同的,使用的代码将更少。试试这个
int sum = list.AsParallel().Sum(person => person.Age);
结果将是相同的,使用更少的代码。即使您解决了
ref小计
问题,这也行不通。你有一个非常明显的比赛条件。您不断更新和读取一个值。那么我如何跟踪共享变量?@BobSwanson一开始不会并行化总和。这比在单个线程中求和要慢得多。除了速度快得多之外,它还将更简单、更不容易出错、更易于维护,等等。即使您解决了ref subtotal
问题,这也行不通。你有一个非常明显的比赛条件。您不断更新和读取一个值。那么我如何跟踪共享变量?@BobSwanson一开始不会并行化总和。这比在单个线程中求和要慢得多。除了速度更快之外,它还更简单、更不容易出错、更易于维护,等等。您大概打算使用+=?正如你将“共享”设置为“年龄”的正值一样?啊,成功了,需要锁定吗?因为它是共享的?大概您打算使用+=?正如你将“共享”设置为“年龄”的正值一样?啊,成功了,需要锁定吗?因为它是共享的?如果我的共享不是int或long,而是十进制,我会使用lock()吗?@BobSwanson正是:)如果我的共享不是int或long,而是十进制,我会使用lock()吗?@BobSwanson正是:)