recently I have seen several SO threads related to Parallel.ForEach mixed with async lambdas, but all proposed answers were some kind of workarounds.
Is there any way how could I write:
List<int> list = new List<int>[]();
Parallel.ForEach(arrayValues, async (item) =>
{
var x = await LongRunningIoOperationAsync(item);
list.Add(x);
});
How can I ensure that list will contain all items from all iterations executed withing lambdas in each iteration?
How will generally Parallel.ForEach work with async lambdas, if it hit await will it hand over its thread to next iteration?
I assume ParallelLoopResult IsCompleted field is not proper one, as it will return true when all iterations are executed, no matter if their actual lambda jobs are finished or not?
recently I have seen several SO threads related to Parallel.ForEach mixed with async lambdas, but all proposed answers were some kind of workarounds.
Well, that's because Parallel
doesn't work with async
. And from a different perspective, why would you want to mix them in the first place? They do opposite things. Parallel
is all about adding threads and async
is all about giving up threads. If you want to do asynchronous work concurrently, then use Task.WhenAll
. That's the correct tool for the job; Parallel
is not.
That said, it sounds like you want to use the wrong tool, so here's how you do it...
How can I ensure that list will contain all items from all iterations executed withing lambdas in each iteration?
You'll need to have some kind of a signal that some code can block on until the processing is done, e.g., CountdownEvent
or Monitor
. On a side note, you'll need to protect access to the non-thread-safe List<T>
as well.
How will generally Parallel.ForEach work with async lambdas, if it hit await will it hand over its thread to next iteration?
Since Parallel
doesn't understand async
lambdas, when the first await
yields (returns) to its caller, Parallel
will assume that interation of the loop is complete.
I assume ParallelLoopResult IsCompleted field is not proper one, as it will return true when all iterations are executed, no matter if their actual lambda jobs are finished or not?
Correct. As far as Parallel
knows, it can only "see" the method to the first await
that returns to its caller. So it doesn't know when the async
lambda is complete. It also will assume iterations are complete too early, which throws partitioning off.