Parallel.For和Break()误会?

Roy*_*mir 10 .net c# parallel-processing .net-4.0 task-parallel-library

我正在研究For循环中的Parallelism Break.

看完这个这个 我还是有一个问题:

我希望这段代码:

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

在得到 6号(0..6).他不仅没有这样做,而且结果长度不同:

02351486
013542
0135642
Run Code Online (Sandbox Code Playgroud)

很烦人.(这里的地狱是Break(){5之后}这里??)

所以我看了msdn

Break可以用于与循环通信,在当前迭代之后不需要运行其他迭代.如果从for循环的第100次迭代调用Break从0到1000并行迭代,则仍应运行小于100的所有迭代,但不需要从101到1000的迭代.

Quesion #1 :

哪个迭代?整个迭代计数器?还是每个帖子?我很确定这是每个帖子.请批准.

Question #2 :

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

core #1 got 0..250
core #2 got 251..500
core #3 got 501..750
core #4 got 751..1000
Run Code Online (Sandbox Code Playgroud)

所以线程core #1会在value=100某个时候遇到并且会中断.这将是他的迭代号 100.但是线程core #4得到了更多的量子,他900现在正在进行中.他超越了他的100'th迭代.他没有指数少于100被停止!! - 所以他会向他们展示所有.

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

Question #3 :

我真的打破了什么时候(i == 5)

PS

我的意思是,来吧!当我这样做时Break(),我希望循环停止.正如我在常规For循环中所做的那样.

Ree*_*sey 10

最多产生6个数字(0..6).

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

当您点击索引为5的循环时,会发送"中断"请求. Break()将导致循环不再处理任何值>5,但处理所有值<5.

但是,任何已经启动的大于5的值仍将被处理.由于各种索引并行运行,因此不再对它们进行排序,因此您可以进行各种运行,其中某些值>5(例如示例中的8)仍在执行中.

哪个迭代?整个迭代计数器?还是每个帖子?我很确定这是每个帖子.请批准.

这是传递给Parallel.For的索引.Break()不会阻止处理项目,但可以保证最多100个项目得到处理,但100以上的项目可能会或可能不会被处理.

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

是.如果你使用像你所示的分区器,一旦你打电话Break(),超出你破坏的物品将不再安排.但是,已经安排的项目(整个分区)将得到完全处理.在您的示例中,这意味着您可能始终处理所有1000个项目.

我怎样才能真正打破(i == 5)?

你是 - 但是当你并行运行时,情况会发生变化.这里的实际目标是什么?如果您只想处理前6项(0-5),则应通过LINQ查询或类似项循环之前限制项.然后,您可以在有Parallel.ForParallel.ForEach没有安全的Break()情况下处理这6个项目.

我的意思是,来吧!当我做Break()时,我希望循环停止.正如我在常规For循环中所做的那样.

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


Eri*_* J. 6

如果从for循环的第100次迭代调用Break,则从0到1000并行迭代

循环的第100次迭代不一定(实际上可能不是)具有索引99的循环.

您的线程可以并将以非常规的顺序运行.遇到.Break()指令时,不会再启动循环迭代.究竟何时发生这种情况取决于特定运行的线程调度的细节.

我强烈建议阅读

并行编程模式

(来自微软的免费PDF)

了解进入TPL的设计决策和设计权衡.