Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 停止vs平行中断_C#_.net_Loops_Task Parallel Library - Fatal编程技术网

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。例如,另请参见,事实并非如此: