我已阅读Microsoft关于运行Parallel.ForEach loop with thread-local variables的指南,这对于计数器和/或更新对象有意义。我的问题是在处理本地布尔变量时需要它。 请考虑以下代码(它只是一个示例,实际代码执行的更多):
public bool ParallelForEachLoopWithThreadLocalBoolVariable(IEnumerable<string> items)
{
bool doWork = false;
Parallel.ForEach<string, bool>(items,
() => false,
(match, loop, madeChange) =>
{
if (match == "valid")
{
madeChange = true;
ProcessMatch(match);
}
return madeChange;
},
(changed) => doWork = changed
);
return doWork;
}
public bool ParallelForEachLoop(IEnumerable<string> items)
{
bool doWork = false;
Parallel.ForEach(items, match =>
{
if (match == "valid")
{
doWork = true;
ProcessMatch(match);
}
});
return doWork;
}
我的最终目标是在ProcessMatch()
方法中传播完成的工作,并返回一个标记,指示整体工作是否有所不同。
我倾向于使用ParallelForEachLoop
方法,因为我相信ParallelForEachLoopWithThreadLocalBoolVariable
会将布尔值分配给每个分区,如果最后一个分区执行工作结束为false,则最终会得到错误的解释(即匹配!=&#34;有效&#34;)。
我担心局部变量doWork
如果被ParallelForEachLoop
方法中的多个线程访问,可能会抛出异常。我真的只需要在条件满足时设置doWork一次,即使它只在整个迭代循环中发生一次(我肯定需要在每个有效匹配上运行ProcessMatch
)。
我的恐惧是否合理?我是否可以使用ParallelForEachLoop
函数而不担心它在某些情况下可能无效?
答案 0 :(得分:1)
首先,为变量指定一个有效值(注意,一个变量 NOT 一个属性)你永远不会抛出 1 的异常,所以你关注的是第二种方法无效。
线程局部变量是这样你可以执行非原子操作(可能有其他事情发生的操作&#34;在#34;它,改变结果)而不必锁定资源,然后你可以执行另一个操作频率较低(在最后一个块中)并锁定该操作并汇总结果。但是,为bool
赋值是一个原子操作,因此不需要使用局部变量。在MSDN示例中,您链接到它们对非整数的整数执行+=
并且需要锁定或使用局部变量,就像在示例中一样,以确保另一个线程没有修改在分配新结果之前,+=
左侧的值。
简而言之,请使用您的第二个版本。
1:为变量赋值是您在Constrained Execution Region
中可以做的少数事情之一