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 函数而不担心它在某些情况下可能无法正常工作?

Parallel.ForEach Loop with Thread-Local boolean

首先,为变量(注意,变量而不是属性(分配一个有效的值,您将永远不会收到抛出的异常1,因此您对第 2 种方法的关注是无效的。

线程局部变量是这样您就可以执行非原子操作(在"期间"发生其他事情的操作,更改结果(,而不必锁定资源,然后您可以降低执行另一个操作的频率(在最后一个块中(并锁定该操作并聚合您的结果。但是,为bool赋值是一项原子操作,因此无需使用局部变量。在您链接到的 MSDN 示例中,它们+=在非原子整数上,并且需要锁定或使用局部变量,就像在示例中所做的那样,以确保在分配新结果之前,另一个线程没有修改+=左侧的值。

简而言之,请使用您的第二个版本。


1:为变量赋值是允许在约束执行区域中执行的少数操作之一