Stop against a gap in parallel.

I find it difficult to understand loopState.Stop() and loopState.Break() . I read MSDN and a few posts about this, but I'm still confused.

As far as I understand, each iteration separator provides the remaining indices for thread processing, and loopState.Stop() stops all threads, and loopState.Break() stops the current thread.

However, let's look at the following situation:

 Parallel.For(0, 100, (i, loopState) => { if (i >= 10) loopState.Break(); Debug.Write(i); }); 

For this loop, I have the following result:

 0 25 1 2 3 4 5 6 7 8 9 10 

I have no idea why the result is 10 and 25 numbers.

Can anybody help?

Postscript I have i5 520M CPU (2 cores => 4 threads)

+10
source share
7 answers

loopState.Break() does not break the function like a return . Thus, the line after loopState.Break() will be executed. After this area has completed for this number, for checks if there was a call to loopState.Break() . If so, all loops are allowed to continue until a number called Break is reached.

In your example, loops from 0 to 24 will be interrupted simultaneously with a cycle of 25 to 49 (and display their "broken" numbers).

The loop 50..74 and 75..99 will not even start, because the second loop 25..49 has already interrupted the entire operation, since their observing numbers are larger than the discontinuous number 10.

+11
source

From the Break() documentation :

A break can be used to communicate with the loop so that no other iterations after the current iteration are performed. For example, if Break is called from the 100th iteration of a for loop, repeating in parallel from 0 to 1000, all iterations less than 100 should be performed, but iterations from 101 to 1000 are not needed.

This means that the current iteration will be completed (so 10 will be printed). Break() also cannot move in time, so 25 will remain printed. What Break() means means that no new iterations beyond 10 will be triggered.

+4
source

if (i >= 10) loopState.Break(); still continue the current iteration. This is printed 10 .

However, iterations (i> = 10) after loopState.Break() called loopState.Break() not start.

But why is 25 printed? The following figure explains why. Since you have 4 threads, 0-99 will be split as 4.

1st line has: 0-24.
The second thread has: 25 - 49.
The third thread has: 50 - 74.
The fourth thread has: 75 - 99.

Based on my understanding, each thread will loop numbers. According to this post , he says

Additional iterations can be performed if they have already been started when calling Break.

Since the second thread starts almost at the same time as the 1st thread, therefore 0, 25 is printed. Then if (i >= 10) loopState.Break(); called when looping 25 in the second thread.

Loops in the 3rd and 4th threads did not start until Break() , so any number greater than 10 was not printed.

image ref: http://www.albahari.com/threading/part5.aspx

+3
source

The gap ensures that all iterations that are currently running are completed.

A stop just completes everything.

+1
source

All methods from the static Parallel class return ParallelLoopResult . This object has two properties - IsCompleted and LowestBreakIteration

When we use loopState.Break() , LowestBreakIteration returns an integer that represents the lowest iteration from which the Break statement is called.

When we use loopState.Stop() , LowestBreakIteration returns null

+1
source

The simplest answer:

both stop and interrupt prevent new iterations from starting. Both guarantee the start of the iteration.

difference - stop - interrupts the iteration to which it called, and break does not.

+1
source
 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')); } }); 

enter image description here

The tasks of "8904" continue to work to complete all iterations of less than 25. Obviously, if the iterations are already completed, which represent values ​​greater than 25, then there will be no possibility of rollback.

If you want to complete the loop as soon as possible and do not care that all previous iterations are completed, ParallelLoopState has a different Stop () method. The Stop method tries to complete the loop as soon as possible - after issuing, no loop task will start a new iteration

0
source

All Articles