Parallel.ForEach Loop with Thread-Local boolean
本文关键字:Thread-Local boolean with Loop ForEach Parallel | 更新日期: 2023-09-27 18:34:55
我已经阅读了Microsoft关于使用线程局部变量运行Parallel.ForEach循环的指南,这对于计数器和/或更新对象很有意义。不过,我的问题是在处理局部布尔变量时需要它。考虑以下代码(这只是一个示例,实际代码的功能更多(:
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 结尾,则最终可能会得到错误的解释(即匹配 != "有效"(。我只是担心局部变量 doWork
如果它被 ParallelForEachLoop
方法中的多个线程访问,可能会引发异常。如果满足条件,我真的只需要设置 doWork 一次,即使它在整个迭代循环中只发生一次(不过我肯定需要在每次有效匹配上运行ProcessMatch
(。我的担心有道理吗?我是否可以使用 ParallelForEachLoop
函数而不担心它在某些情况下可能无法正常工作?
首先,为变量(注意,变量而不是属性(分配一个有效的值,您将永远不会收到抛出的异常1,因此您对第 2 种方法的关注是无效的。
线程局部变量是这样您就可以执行非原子操作(在"期间"发生其他事情的操作,更改结果(,而不必锁定资源,然后您可以降低执行另一个操作的频率(在最后一个块中(并锁定该操作并聚合您的结果。但是,为bool
赋值是一项原子操作,因此无需使用局部变量。在您链接到的 MSDN 示例中,它们+=
在非原子整数上,并且需要锁定或使用局部变量,就像在示例中所做的那样,以确保在分配新结果之前,另一个线程没有修改+=
左侧的值。
简而言之,请使用您的第二个版本。
1:为变量赋值是允许在约束执行区域中执行的少数操作之一