NDepend Blog

Improve your .NET code quality with NDepend

How to collect return values from Parallel.ForEach?

January 26, 2022 1 minutes read

How to collect return values from Parallel.ForEach

Today I took 10 minutes to answer the 9 years old stackoverflow’s question: How do I collect return values from Parallel.ForEach? I though the improved solution deserved a quick blog post since it hasen’t been mentioned.

The accepted answer proposes to use a concurrent collection to store the result:

Concurrent collection is necessarily expensive since internally it relies on threading lock. There is 89 mentions of “lock” in the source code of ConcurrentBag<T>.

However in the particular case where the size of the collection is known upfront – and this is often the case in practice – an array of the size of the inputs can be used to store outputs. Now each loop receives its very own index, both to access the input and store the output. There is no risk of concurrent access collision here:

There is a bonus with this solution: outputs are stored with the same order as inputs, while the order is random when using a concurrent collection.

This is a trick we use for more than a decade in the NDepend code base, even before TPL (Task Parallel Library) was released. The rule of thumb is to avoid concurrent access when possible, and with a bit of astute this is often possible.