Maybe I did not understand it right ... all the Parallel class issue :(
But from what I am reading now, I understand that when I use the Parallel I actually mobilize
Short answer: Parallel.ForEach()
does not “mobilize all the threads”. And any operation that schedules some work on the ThreadPool
(which Parallel.ForEach()
does) can cause creation of new thread in the pool.
Long answer: To understand this properly, you need to know how three levels of abstraction work: Parallel.ForEach()
, TaskScheduler
and ThreadPool
:
Parallel.ForEach()
(and Parallel.For()
) schedule their work on a TaskScheduler
. If you don't specify a scheduler explicitly, the current one will be used.
Parallel.ForEach()
splits the work between several Task
s. Each Task
will process a part of the input sequence, and when it's done, it will request another part if one is available, and so on.
How many Task
s will Parallel.ForEach()
create? As many as the TaskScheduler
will let it run. The way this is done is that each Task
first enqueues a copy of itself when it starts executing (unless doing so would violate MaxDegreeOfParallelism, if you set it). This way, the actual concurrency level is up to the TaskScheduler
.
Also, the first Task
will actually execute on the current thread, if the TaskScheduler
supports it (this is done using RunSynchronously()).
The default TaskScheduler simply enqueues each Task
to the ThreadPool
queue. (Actually, it's more complicated if you start a Task
from another Task
, but that's not relevant here.) Other TaskScheduler
s can do completely different things and some of them (like TaskScheduler.FromCurrentSynchronizationContext()) are completely unsuitable for use with Parallel.ForEach()
.
The ThreadPool
uses quite a complex algorithm to decide exactly how many threads should be running at any given time. But the most important thing here is that scheduling new work item can cause the creating of a new thread (although not necessarily immediately). And because with Parallel.ForEach()
, there is always some item queued to be executed, it's completely up to the internal algorithm of ThreadPool
to decide the number of threads.
Put together, it's pretty much impossible to decide how many threads will be used by a Parallel.ForEach()
, because it depends on many variables. Both extremes are possible: that the loop will run completely synchronously on the current thread and that each item will be run on its own, newly created thread.
But generally, is should be close to optimal efficiency and you probably don't have to worry about all those details.