c# - Parallel.For 和 Break() 的误解?

标签 c# .net .net-4.0 parallel-processing task-parallel-library

我正在研究 For 循环中的并行中断。

看完this this我还有一个问题:

我希望这段代码:

 Parallel.For(0, 10, (i,state) =>  
     { 
                Console.WriteLine(i); if (i == 5) state.Break(); 
     }

最多生成 6 个数字 (0..6)。 不仅他没有这样做,而且结果长度不同:

02351486
013542
0135642

非常烦人。 (Break() {after 5} 到底在哪里??)

于是我看了一下msdn

Break may be used to communicate to the loop that no other iterations after the current iteration need be run. If Break is called from the 100th iteration of a for loop iterating in parallel from 0 to 1000, all iterations less than 100 should still be run, but the iterations from 101 through to 1000 are not necessary.

问题#1:

哪些迭代?整体迭代计数器?还是每个线程?我很确定这是每个线程。请批准。

问题#2:

假设我们正在使用并行 + 范围分区(由于元素之间的 cpu 成本没有变化),因此它在线程之间划分数据。所以如果我们有 4 个核心(并且在它们之间完美划分):

core #1 got 0..250
core #2 got 251..500
core #3 got 501..750
core #4 got 751..1000

因此 core #1 中的线程将在某个时候遇到 value=100 并中断。 这将是他的迭代编号 100 。 但是 core #4 中的线程获得了更多的量子,他现在在 900 上。他远超他的第 100 次 迭代。 他没有索引减去 100 被阻止!! - 所以他会展示给他们看。

我说得对吗?这就是我在示例中获得超过 5 个元素的原因吗?

问题#3:

(i == 5) 时,我如何真正崩溃?

附:

我的意思是,来吧!当我执行 Break() 时,我希望循环停止。 与我在常规 For 循环中所做的完全一样。

最佳答案

To yield at most 6 numbers (0..6).

问题是这不会产生最多 6 个数字

发生的事情是,当您遇到索引为 5 的循环时,您会发送“中断”请求。 Break()将导致循环不再处理任何值 >5 ,但处理所有值 <5 .

但是,任何已经开始的大于 5 的值仍将得到处理。由于各种索引并行运行,它们不再有序,所以你会得到各种运行,其中一些值 >5 (例如您示例中的 8)仍在执行中。

Which iterations ? the overall iteration counter ? or per thread ? I'm pretty sure it is per thread. please approve.

这是传递给 Parallel.For 的索引。 Break() 不会阻止处理项目,但会保证处理最多 100 个项目,但可能会处理也可能不会处理超过 100 个的项目。

Am I right ? is that is the reason why I get more than 5 elements in my example ?

是的。如果你像你展示的那样使用分区器,只要你调用 Break() ,您打破的项目将不再被安排。但是,已安排的项目(即整个分区)将得到完全处理。在您的示例中,这意味着您可能始终处理所有 1000 个项目。

How can I truly break when (i == 5) ?

你是 - 但当你并行运行时,事情就变了。这里的实际目标是什么?如果您只想处理前 6 个项目 (0-5),您应该在通过 LINQ 查询或类似查询循环遍历它们之前限制这些项目。然后您可以处理 Parallel.For 中的 6 个项目或 Parallel.ForEach没有 Break()不用担心。

I mean , come on ! when I do Break() , I want things the loop to stop. excactly as I do in regular For loop.

你应该使用 Stop() 而不是 Break()如果你想让事情尽快停止。这不会阻止项目停止已经运行,但不会再安排任何项目(包括索引较低或枚举中比您当前位置更早的项目)。

关于c# - Parallel.For 和 Break() 的误解?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12784530/

相关文章:

c# - WinFORMS 中的 WPF 用户控件 : Project Structuring

c# - 使用 Sitecore Webforms For Marketers 生成摘要报告

c# - 如何避免在 web.config 中添加程序集版本?

.net - 方法内联优化会导致竞争条件吗?

c# - 为什么我不能 "see"这个枚举扩展方法?

c# - 通过使用 LINQ 筛选两个列表来创建字典

c# - 使用依赖注入(inject)进行硬件抽象

c# - 如何打印 GMap.NET map ?

c# - 如何轻松初始化元组列表?

c# - 多线程时是否必须锁定数据库连接?