Search code examples
c#parallel-processingparallel.foreach

Differences between Parallel.ForEach and await ForEachAsync


Is there any reason to choose Parallel.ForEach instead of await ForEachAsync in any situation (or vice-versa)? or they are virtually the same?

await collection.ForEachAsync( m => { m.DoSomething(); } );

VS

Parallel.ForEach( collection, m => { m.DoSomething(); } );

Solution

  • They are not 'virtually the same' at all.

    When you use functions from the Parallel class such as Parallel.ForEach() you are invoking some action, in which that action is broken up into multiple smaller actions, each carried out on different threads (aka multi-threaded).

    ForEachAsync on the other hand is not necessarily multi-threaded. It is asynchronous and asynchronous operations are not multi-threaded ones (well they can be, but don't have to be, that depends on the implementation).

    I strongly suggest reading the following post which goes into far more detail on the topic.

    As for you question of

    Is there any reason to choose Parallel.ForEach instead of await ForEachAsync in any situation

    The answer is most definitely that there are reasons to do so, but in order to determine what kind of scenarios you would use one or the other, you have to understand them both.

    Here's a simple example:

    You have a collection of objects and you want to iterate over them and perform some kind of action. Do you care about the order in which those actions occur? If so do not use Parallel.ForEach() as there is no guarantee of the order in which they are invoked (due to its multi-threaded nature).

    EDIT:

    In your example, it all depends on how many items are in collection and how process-heavy DoSomething() is.

    The reason for that is because Parallel.ForEach() is not free. There are trade-offs to be made. Setting up a multi-threaded environment takes time and if collection is small and/or DoSomething() doesn't take too long, then the time spent setting up those threads would be better (and usually faster) spent with a single-threaded async operation.

    On the other hand, if collection is large and/or DoSomething() is a process-heavy task then Parallel.ForEach() will most definitely be the most performant option.