Is Parallel.ForEach obsolete. old, out of fashion? Is Parallel.ForEach obsolete. old, out of fashion? multithreading multithreading

Is Parallel.ForEach obsolete. old, out of fashion?


I don't think Parallel.ForEach is obsolete.

Ever since introducing the Task Parallel Library (TPL) with .NET 4, Microsoft has distinguished between "Data Parallelism" (e.g. Parallel.ForEach) and "Task Parallelism" (Task). From MSDN:

  • "Data parallelism refers to scenarios in which the same operation is performed concurrently (that is, in parallel) on elements in a source collection or array."
  • "[T]ask parallelism refers to one or more independent tasks running concurrently."

(Emphasis by me. Like dcastro commented (above): "Your friend is confusing parallelism with asynchrony.")

These two types of parallelism/concurrency pursue different goals, so the TPL offers different capabilities for each of them.

Conceptually, Task.WhenAll belongs into the task parallelism category, so I don't think it obsolesces something that belongs to the other (data parallelism) category.


Parallel.ForEach (and PLINQ as a whole) has abilities that are not available in the async language support.

For example, you can limit the degree of parallelism (eg. 100 items to process, but do no more that 10 at a time). Thus it is not obsolete.

Fundamentally async is about making concurrent operations – without any assumptions of threading – easier to write. PLINQ is about computation making use of many cores.

I suspect your colleague is reading too much into direct use of Task Parallel Library (TPL) largely being unnecessary with async in the language (except for the return type of async functions). But PLINQ was always a different layer over TPL. If anything PLINQ and async are two separate ways to make use of TPL for different purposes.


async and await have nothing at all to do with parallelism. They are technologies used to make existing asynchronous APIs easier to consume and expose. async and await do not initiate parallelism or concurrency. In fact await ends parallelism by waiting for something that is already running.

Parallel.ForEach is used to process a set of homogeneous items in the same way on multiple cores. You can simulate Parallel.ForEach by spawning a big number of tasks. There is no advantage in doing that. In fact it introduces inefficiencies and obfuscates the code. It is possible and works but it is an inferior way of doing things if Parallel.ForEach is applicable.

I think your colleague does not understand that await really just waits. It does not start something.

Use Parallel.* and PLINQ (mostly) for CPU-bound work.