我可以使用parallel.ForEach调用不同的函数吗?
我有一个运行的foreach循环。我正在研究并行函数。可以将以下代码转换为使用并行编程吗?我可以使用parallel.ForEach调用不同的函数吗?
int result ;
int counter;
foreach(DataRow dr in ds.Tables[0].Rows) {
switch(dr["Gender"].ToString()) {
case "Male":
result = functionMale(dr["Gender"].ToString());
counter += result;
break;
case "Female":
result = functionFemale(dr["Gender"].ToString());
counter += result;
break;
default:
result = functionUnkown(dr["Gender"].ToString());
counter += result;
break;
}
}
根据我所看到的内容,我目前只有以下内容。
Parallel.ForEach(ds.Tables[0].AsEnumerable(), dr => {
var result = functionMale(dr["Gender"].ToString();
});
任何想法?谢谢
当然,这是完全可能的。 Parallel.ForEach心不是做任何一种特定的魔法在这种情况下(比其他线程),所以它只是看起来像这样:
ds.Tables[0].Rows.AsEnumerable().AsParallel().Sum(x =>
{
DataRow dr = x as DataRow;
switch(dr["Gender"].ToString())
{
case "Male":
// Stuff
case "Female";
// Stuff
default:
// Stuff
}
return counter;
});
这应该聚集的功能,所有的值,因为除了是可交换的。
你可以尝试这样的事情,更实用的风格:
var counter =
ds.Tables[0].AsEnumerable()
.AsParallel()
.Select(dr => {
var gender = dr["Gender"].ToString();
switch(gender)
{
case "Male":
return functionMale(gender);
case "Female":
return functionFemale(gender);
default:
return functionUnkown(gender);
}
})
.Sum();
它是喜欢首先(内部)选择列表中的所有记录,然后总和功能? – Pankaj 2012-04-17 15:45:48
是的 - 但选择被称为“它走了” - 所以它可能会具有相同的性能配置文件,从上面的六个字母变量 – 2012-04-17 16:21:21
你可以使用AsParallel
和Sum
:
Func<string, int> calculateGender =
gender =>
{
// nb: I don't know why you pass the gender to the method, but
// I've left your intent as-is
switch (gender)
{
case "Male": return functionMale(gender);
case "Female": return functionFemale(gender);
default: return functionUnknown(gender);
}
};
int counter = ds.Tables[0].AsEnumerable()
.AsParallel()
.Sum(dr => calculateGender(dr["Gender"].ToString()));
的PLINQ方法是轻松了许多,但只是为了圆这里的答案是你如何做到这一点与Parallel.ForEach
。
int counter = 0;
Parallel.ForEach(ds.Tables[0].AsEnumerable(),
() => /* subtotal initializer */
{
return 0;
},
(dr, state, subtotal) => /* loop body */
{
switch(dr["Gender"].ToString())
{
case "Male":
subtotal += functionMale(dr["Gender"].ToString());
break;
case "Female":
subtotal += functionFemale(dr["Gender"].ToString());
break;
default:
subtotal += functionUnkown(dr["Gender"].ToString());
break;
}
},
subtotal => /* subtotal accumulator */
{
Interlocked.Add(ref counter, subtotal);
});
这是如何工作的。第一个lambda表达式初始化TPL释放的每个工人的本地小计仓。第二个lambda表达式对集合中的每个项目执行一次,并更新本地小计仓。第三个lambda表达式将本地小计箱组合到最终总计中。
使用Parallel.ForEach
和AsParallel
与合计之间的一个有趣的区别是小计累计到最终值的方式。 Parallel.ForEach
在工作线程上执行此操作,因此需要线程安全操作Interlocked.Add
。 AsParallel
使用相同的分区策略,但会在调用者线程上累积小计。
以下是C#中并行环境中的聚合链接http://msdn.microsoft.com/en-us/library/ff963547.aspx – Servy 2012-04-17 15:24:40