C# 停止vs平行中断
我很难理解C# 停止vs平行中断,c#,.net,loops,task-parallel-library,C#,.net,Loops,Task Parallel Library,我很难理解loopState.Stop()和loopState.Break()。我读过MSDN和几篇关于它的帖子,但我仍然感到困惑 据我所知,每个迭代分区器都会为要处理的线程提供剩余的索引,loopState.Stop()停止所有线程,loopState.Break()停止当前线程 然而,让我们考虑以下情况: Parallel.For(0, 100, (i, loopState) => { if (i >= 10) loopState.Break();
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个数字
有人能帮忙吗
另外,我有i5 520M CPU(2个内核=>4个线程)loopState.Break()
不像返回那样中断函数。因此,loopState.Break()
之后的行仍将被执行。在该数字的作用域结束后,
的检查是否调用了loopState.Break()
。如果是这样,则允许所有循环继续,直到达到名为Break
的数字
在您的示例中,从0到24的循环将与从25到49的循环同时中断(并显示其“中断”编号)
循环50..74和75..99甚至无法启动,因为第二个循环25..49已中止整个操作,因为它们的起始编号大于断开编号10。来自:
Break可用于向循环传达在当前迭代之后不需要运行其他迭代。例如,如果在从0到1000并行迭代的For循环的第100次迭代中调用Break,则仍应运行小于100的所有迭代,但不需要从101到1000的迭代
这意味着当前迭代仍将完成(因此10
将被打印)Break()
也不能进行时间旅行,因此25
将保持打印状态。Break()
的意思是,除了10
之外,不会启动任何新的迭代。Break确保当前运行的所有迭代都将完成
停止只是终止一切。如果(i>=10)loopState.Break()代码>仍将继续当前迭代。所以10
被打印出来
但是,调用loopState.Break()
后的迭代(i>=10)将不会开始
但是为什么要打印25
?下图将解释原因。由于您有4个线程,0-99将被划分为4个
第一个螺纹有:0-24
第二个线程有:25-49
第三个螺纹有:50-74
第四个线程有:75-99
根据我的理解,每个线程都将循环数字本身。据报道,它说
如果在调用Break时已经开始了其他迭代,则可以运行这些迭代
由于第二个线程几乎与第一个线程同时启动,因此打印0,25
。然后如果(i>=10)loopState.Break()在第二个线程中循环25
时调用code>
在调用Break()
之前,第三个和第四个线程中的循环没有启动,因此任何大于10
的数字都没有打印出来
image ref:来自静态并行类的所有方法返回并行循环结果
。此对象有两个属性-已完成和最低的BreakIteration
当我们使用loopState.Break()
时,LowestBreakIteration
返回一个整数,该整数表示调用Break语句的最低迭代次数
当我们使用loopState.Stop()
时,LowestBreakIteration
返回null
最简单的答案:
停止和中断都会阻止新的迭代开始。两者都确保开始的迭代完成
difference-stop-中止它调用的迭代,break不会
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方法尝试结束
循环一旦发出,任何循环任务都不会开始新的迭代loopState.Break()是否退出所有线程?我习惯于loopState.Stop()这样做。为了澄清我之前的评论:我现在知道前两个循环是如何停止的,但为什么其他两个线程甚至没有启动?Break能够终止多个线程吗?如果是这样的话,它是如何做到的?请参阅关于停止与中断的一个好答案:@MichałJankowski其他两个不会启动,可能是因为他们没有时间-如果你在loopState.Break()
之前放置一个线程。Sleep(1)它们有时会开始执行。@svick+Michal:我调整了我的答案。我希望我的答案尽可能简单。但这太简单了。谢谢你的更新,那不是真的。Stop()导致不再执行新的迭代。但是仍然允许所有正在运行的迭代/线程完成。如果要在操作中提前退出,则需要测试state.IsStopped。例如,另请参见,事实并非如此: