C# 我可以使用parallel.ForEach调用不同的函数吗?
我有一个运行的foreach循环。我正在研究并行函数。是否可以将以下代码转换为使用并行编程C# 我可以使用parallel.ForEach调用不同的函数吗?,c#,asp.net,.net,multithreading,parallel-processing,C#,Asp.net,.net,Multithreading,Parallel Processing,我有一个运行的foreach循环。我正在研究并行函数。是否可以将以下代码转换为使用并行编程 int result ; int counter; foreach(DataRow dr in ds.Tables[0].Rows) { switch(dr["Gender"].ToString()) { case "Male": result = functionMale(dr["Gender"].ToString()); coun
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();
您可以使用AsParallel和Sum:
PLINQ方法要简单得多,但这里要对答案进行四舍五入,您将如何使用Parallel.ForEach实现这一点 这就是它的工作原理。第一个lambda表达式初始化TPL分配的每个工人的本地小计箱。第二个lambda表达式对集合中的每个项执行一次,并更新本地小计bin。第三个lambda表达式将本地小计箱组合到最终合计箱中
对聚合使用Parallel.ForEach和AsParallel的一个有趣的区别在于小计累加到最终值的方式。Parallel.ForEach在工作线程上执行此操作,因此需要线程安全操作interlocted.Add。AsParallel使用相同的分区策略,但会在调用线程上累积小计。这里有一个指向C中并行环境中聚合的链接,它们确实具有这种依赖性;他正在汇总数据。用计数器代码更新;我的缺点是,我没有看到聚合。这就像是先在内部选择列表中的所有记录,然后选择sum函数吗?是的,但select是按原样调用的,因此它可能与上面的另一个答案(从SixLetterVariables)具有相同的性能配置文件。我有点困惑@戴夫也在做同样的事情。那么哪一个更快?@PankajGarg:我不知道,在实践中可能没有什么不同。在幕后可能完全一样。@sixlettervariables:这将减少处理时间?@MrM:这一切都取决于你有多少行,可计算的时间,每个性别计算所需的时间,有时并行化的工作负载并没有更快,有时甚至更慢。如果不尝试,你可能不会知道。
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()));
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);
});