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 THIS?
{
Process[] processes = Process.GetProcesses();
List<String> ProcessNames = new List<String>();
Parallel.ForEach(processes, curItem => {
ProcessNames.Add(processes.ProcessName);
}
});
return ProcessNames;
}
Lastly what is the behavior of the return keyword inside a Parallel For or ForEach loop?
IE: Does it immediately terminate all threads? Will it cause any artifacts that you might not expect?
Hopefully what I am asking makes sense.
PS: To be more specific. Looking at the first example is my modification of the String threadsafe and contain the value I expect because of the return statement? And in the second example is my modification of the List Collection threadsafe? Will all the values I expect be added?
The main reason for using the foreach package is that it supports parallel execution, that is, it can execute those repeated operations on multiple processors/cores on your computer, or on multiple nodes of a cluster.
The execution of Parallel. Foreach is faster than normal ForEach.
It's not uncommon to break the execution of a for/foreach loop using the 'break' keyword. A for loop can look through a list of integers and if the loop body finds some matching value then the loop can be exited.
I'd use PLINQ here:
return Process
.GetProcesses()
.AsParallel()
.SingleOrDefault(p => p.Handle == this._handle);
I wonder whether the amount of data you're handling here merits going parallel...
To answer your question more directly, in order to handle early exit from a parallel loop you should look into overloads that hand a ParallelLoopState to the executing delegate. This can be used to control early loop termination.
EDIT:
The errors you are seeing is because your process does not have sufficient privilege to access the handle of the processes you inspecting. A brute force way of handling this would be as follows:
Process
.GetProcesses()
//.AsParallel()
.Where(p=>{try{var h=p.Handle;}catch{return false;}return true;})
.SingleOrDefault(p => p.Handle == this._handle)
Of course, assuming this._handle
refers to the handle of the currently executing process:
Process.GetCurrentProcess()
would surely be a better fit?
return
inside a parallel foreach loop is basically the same as a continue
in a normal loop, because the return
is inside the delegate that is executed for each item. This means, it doesn't terminate any threads and especially doesn't terminate execution of the parallel foreach loop.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With