Return value and keyword inside Parallel ForEach or For loop

What is the correct way to return a value from a Parallel ForEach or For loop?

For example, is the following code correct / threadsafe?

{ Process[] processes = Process.GetProcesses(); String ProcessName = String.Empty; Parallel.ForEach(processes, curItem => { if (curItem.Handle == this._handle) { ProcessName = curItem.ProcessName; return; } }); return ProcessName; } 

OR THAT?

 { Process[] processes = Process.GetProcesses(); List<String> ProcessNames = new List<String>(); Parallel.ForEach(processes, curItem => { ProcessNames.Add(processes.ProcessName); } }); return ProcessNames; } 

Finally, what is the behavior of the return keyword inside a Parallel For or ForEach loop?

IE: does it terminate all threads immediately? Could this cause any artifacts you don't expect?

Hope what I ask makes sense.

PS: To be more specific. Looking at the first example, is this my modification of the String stream string and contains the value that I expect due to the return statement? And in the second example, my modification of List List threadsafe? Will all the values ​​I expect be added?

+7
source share
4 answers

I would use PLINQ here:

 return Process .GetProcesses() .AsParallel() .SingleOrDefault(p => p.Handle == this._handle); 

I wonder if the amount of data you're processing here is worth it in parallel ...

To more accurately answer your question, in order to handle an early exit from a parallel loop, you should examine the overloads that pass ParallelLoopState to the executing delegate. This can be used to control the early end of a cycle.

EDIT:

The errors you see are because your process does not have sufficient privileges to access the handle of the processes you are checking. To do this, you can use the following methods:

 Process .GetProcesses() //.AsParallel() .Where(p=>{try{var h=p.Handle;}catch{return false;}return true;}) .SingleOrDefault(p => p.Handle == this._handle) 

Of course, if this._handle refers to the handle of the currently executing process:

 Process.GetCurrentProcess() 

will probably be better suited?

+9
source

return inside a parallel foreach loop is basically the same as continue in a normal loop, because return is inside the delegate that runs for each element. This means that it does not terminate any threads and, in particular, does not complete the execution of a parallel foreach loop.

+6
source

All of the above answers +:

If you want to signal that the loop should stop, you should use ParallelLoopState (you can access this object by passing Action<T, ParallelLoopState> instead of the Action<T> delegate. The state object has a method, for example .Stop() or .Break() , which will mean that you want to stop executing your loop (and a few other useful properties, try it yourself).

+6
source

Wrong. Are you looking for value? Parallel.ForEach is the wrong solution here. You are looking for a reduction , and ForEach performs the mapping. Parallel recovery can be performed using PLINQ.

+5
source

All Articles