在 parallel.foreach 范围之外增加计数值

发布于 2024-08-23 22:20:22 字数 188 浏览 4 评论 0原文

如何增加parallel.foreach 循环范围之外的整数值?同步对并行循环之外的对象的访问的最简单方法是什么?

var count = 0;
Parallel.ForEach(collection, item =>
{
  action(item);
  // increment count??
}

How can I increment an integer value outside the scope of a parallel.foreach loop? What's is the lightest way to synchronize access to objects outside parallel loops?

var count = 0;
Parallel.ForEach(collection, item =>
{
  action(item);
  // increment count??
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一身骄傲 2024-08-30 22:20:22

我喜欢打败死马! :)

从多个线程增加计数的“最轻”方法是:

Interlocked.Increment(ref count);

但正如其他人指出的那样:如果您在 Parallel.ForEach 内执行此操作,那么您可能做错了什么。

我怀疑由于某种原因您正在使用 ForEach 但您需要正在处理的项目的索引(它永远无法与 Parallel.ForEach 一起使用)。我很接近吗?为什么需要计数?你想施展哪种巫毒魔法?

更新:

如果您的键是 URI 并且值是 TAnswer,那么使用 ConcurrentDictionary 似乎是安全的。只要您不尝试使用计数来引用集合中的元素,我就没有看到问题。

最后...

如果您需要计数器,请使用 Parallel.For 循环...它会安全地为您递增计数器。

I like to beat dead horses! :)

The "lightest" way to increment the count from multiple threads is:

Interlocked.Increment(ref count);

But as others have pointed out: if you're doing it inside Parallel.ForEach then you're probably doing something wrong.

I'm suspecting that for some reason you're using ForEach but you need an index to the item you're processing (it will never work with Parallel.ForEach). Am I close? Why do you need the count? What sort of VooDoo magic are you trying to do?

UPDATE:

You seem to be safe with the ConcurrentDictionary if your key is the URI and the value is TAnswer. I don't see a problem as long as you don't try to use the count to reference elements in your collection.

Finally...

If you need a counter, then use the Parallel.For loop... it safely increments the counter for you.

脸赞 2024-08-30 22:20:22

以这种方式使用 Interlocked.Increment 方法。

int count = 0;
Parallel.ForEach(users, (u) =>
{
    var currentCount = Interlocked.Increment(ref count);
    Log(String.Format("Step {0} of {1}", currentCount, users.Count));
});

Use Interlocked.Increment method in this way.

int count = 0;
Parallel.ForEach(users, (u) =>
{
    var currentCount = Interlocked.Increment(ref count);
    Log(String.Format("Step {0} of {1}", currentCount, users.Count));
});
自在安然 2024-08-30 22:20:22

Parallel.Foreach 附带了一个额外的 重载 非常适合当您只想对循环内的内容进行计数时的情况。

    int totalCount = 0;
    Parallel.ForEach(files, () => 0, (file, loopState, localCount) =>
    {
        if(ProcessFile(file))
           localCount++;
    
        return localCount;
    
    }, localCount => Interlocked.Add(ref totalCount, localCount));

    Console.WriteLine($"Processed {totalCount}/{files.Length} files.");

您可以在循环体中注入线程本地计数变量并像往常一样递增/递减它。这样,您就不会在每个循环周期中进行 InterLocked 调用。相反,在每个并行任务结束时只有一个 Interlocked.Add 调用来汇总总计数。

请注意,使用此方法时,您不应在循环体内使用 totalCount。如果您的问题需要从循环体内访问totalCount,您必须使用InterLocked.Incerment 方法,如其他答案中所述。

Parallel.Foreach comes along with an extra overload that perfectly fits for that kind of scenario when you just want to count things inside the loop.

    int totalCount = 0;
    Parallel.ForEach(files, () => 0, (file, loopState, localCount) =>
    {
        if(ProcessFile(file))
           localCount++;
    
        return localCount;
    
    }, localCount => Interlocked.Add(ref totalCount, localCount));

    Console.WriteLine(
quot;Processed {totalCount}/{files.Length} files.");

Into the loop body you can inject a thread local count varialble and increment/decrement it as usual. This way you do not have an InterLocked call in every loop cycle. Instead there is just one Interlocked.Add call at the end of each parallel Task summing up totalCount.

Note that with this method you should not use totalCount from within the loop body. If your problem requires to access totalCount from within the loop body you have to use the InterLocked.Incerment method as describe in other answers.

献世佛 2024-08-30 22:20:22

使用Interlocked.Increment

我不会在并行 foreach 内增加事物(当然,除非您使用 Interlocked.Increment 或其他一些锁定机制)。那不是它的目的。并行 foreach 应该仅与在共享状态下不会产生副作用的操作一起运行。在并行 foreach 中增加一个值将导致您很可能试图避免的问题。

Use Interlocked.Increment.

I wouldn't increment things inside a parallel foreach (unless, of course, you're using Interlocked.Increment or some other locking mechanism). That's not what it's for. The Parallel foreach should be run only with actions that cause no side effects in shared state. To increment a value in a parallel foreach will cause the very problem you're more than likely trying to avoid.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文