我很难理解loopState.Stop()
和loopState.Break()
。我已阅读MSDN和几篇关于它的帖子,但我仍感到困惑。
据我所知,每个迭代分区程序都会为要处理的线程提供剩余索引,loopState.Stop()
会停止所有线程,loopState.Break()
会停止当前线程。
但是让我们考虑以下情况:
Parallel.For(0, 100, (i, loopState) =>
{
if (i >= 10)
loopState.Break();
Debug.Write(i);
});
对于这个循环,我有结果:
0 25 1 2 3 4 5 6 7 8 9 10
我不知道为什么在结果中有10个和25个数字。
任何人都可以提供帮助?
P.S。我有i5 520M CPU(2核= 4线程)
答案 0 :(得分:11)
loopState.Break()
不会像return
那样破坏函数。因此,loopState.Break()
之后的行仍将执行。在该范围的该范围结束后,for
会检查是否已调用loopState.Break()
。如果是这样,则允许所有循环继续,直到达到名为Break
的数字。
在你的例子中,0到24的循环将在循环25到49的同时断开(并显示它们的“断开”数字)。
循环50..74和75..99甚至不会开始,因为第二个循环25..49已经中止了整个for-operation,因为它们的数据大于破碎数10。
答案 1 :(得分:3)
来自the documentation of Break()
:
Break可以用于与循环通信,在当前迭代之后不需要运行其他迭代。例如,如果从for循环的第100次迭代中调用Break从0到1000并行迭代,则仍应运行小于100的所有迭代,但不需要从101到1000的迭代。
这意味着当前的迭代仍将完成(因此打印10
)。 Break()
也无法进行时间旅行,因此25
将保持打印状态。 Break()
的含义是,10
以外的新次迭代不会开始。
答案 2 :(得分:2)
if (i >= 10) loopState.Break();
仍会继续当前的迭代。因此打印10
。
但是,调用loopState.Break()
后的迭代次数(i> = 10)将无法启动。
但为什么打印25
?下图将解释原因。由于你有4个线程,0-99将被分为4个。
第一个帖子有:0-24。
第二个帖子有:25 - 49
第3个帖子有:50 - 74
第4个帖子有:75 - 99.
根据我的理解,每个线程都会循环数字本身。根据{{3}},它说
如果在调用Break时已经启动了其他迭代,则可以运行。
由于第二个线程几乎与第一个线程同时启动,因此打印0, 25
。然后在第二个帖子中循环if (i >= 10) loopState.Break();
时调用25
。
第3和第4个线程中的循环在Break()
被调用之前没有启动,因此任何大于10
的数字都没有打印。
图片参考:this post
答案 3 :(得分:1)
中断可确保完成当前正在运行的所有迭代。
停止只会终止所有内容。
答案 4 :(得分:1)
静态Parallel
类中的所有方法都返回ParallelLoopResult
。此对象有两个属性 - IsCompleted
和LowestBreakIteration
当我们使用loopState.Break()
时,LowestBreakIteration
返回一个整数,表示从中调用Break语句的最低迭代次数
当我们使用loopState.Stop()
时,LowestBreakIteration
会返回null
答案 5 :(得分:1)
最简单的答案:
停止和中断都会阻止新的迭代开始。两者都确保开始迭代完成。
差异 - 停止 - 中止它所调用的迭代并中断不会。
答案 6 :(得分:0)
void Log(string prefix, bool isBreak=false)
{
var msg = isBreak ? " Break" : "";
Console.WriteLine($"{prefix} task: {Task.CurrentId.ToString().PadLeft(3,'0')} {msg}");
}
long lockFlag=0;
Parallel.For(0, 130, (i, loopState) =>
{
if (i >= 10 && Interlocked.Read(ref lockFlag)==0)
{
lockFlag=Interlocked.Increment(ref lockFlag);
loopState.Break();
//Statement after break will still execute for current iteration
Log(i.ToString().PadLeft(3,'0'),true);
}
else
{
Log(i.ToString().PadLeft(3,'0'));
}
});
任务“ 8904”继续运行以完成所有小于25的迭代。显然,如果已经完成了代表大于25的值的迭代,则 将无法回滚。
如果您确实想尽快终止循环,而不必担心要保证所有先前的迭代 完成后,ParallelLoopState还有另一个名为 Stop()的方法。 Stop方法尝试结束 尽快循环-发出后,没有循环任务将开始新的迭代