Using System.Threading.Tasks.Parallel to create a new thread in a thread pool?

Perhaps I did not understand this correctly ... all the problems of the Parallel class :(

But from what I'm reading now, I understand that when I use Parallel, I actually mobilize all the threads that exist in threadPool for some task / mission.

For example :

var arrayStrings = new string[1000]; Parallel.ForEach<string>(arrayStrings, someString => { DoSomething(someString); }); 

So, Parallel.ForEach in this case mobilizes all the threads that exist in threadPool for the DoSomething task / mission.

But does Parallel.ForEach call any new thread?

Clearly there will be no 1000 new threads. But let's assume that there are 1000 new threads, in which case threadPool releases the whole thread that it holds so, in this case ... Parallel.ForEach will create any new thread?

+6
source share
4 answers

Short answer: Parallel.ForEach() does not "mobilize all threads." And any operation that plans some work on ThreadPool (which is Parallel.ForEach() ) can cause the creation of a new thread in the pool.

Long answer: To understand this correctly, you need to know how the three levels of abstraction work: Parallel.ForEach() , TaskScheduler and ThreadPool :

  • Parallel.ForEach() (and Parallel.For() ) are planning their work on TaskScheduler . If you do not specify the scheduler explicitly, the current one is used .

    Parallel.ForEach() shares work between several Task s. Each Task will process a part of the input sequence, and when it is completed, it will request another part, if available, etc.

    How many Task will Parallel.ForEach() create? Whole TaskScheduler will let you run. The way this is done is that each Task first queues a copy of itself when it starts execution (unless it violates MaxDegreeOfParallelism , if you installed it). Thus, the actual concurrency level corresponds to the TaskScheduler .

    In addition, the first Task will actually be executed in the current thread, if it supports TaskScheduler (this is done using RunSynchronously() ).

  • By default, the TaskScheduler simply queues the Task ThreadPool . (Actually, it’s more difficult if you run Task from another Task , but it doesn’t matter here.) Other TaskScheduler can do completely different things, and some of them (for example, TaskScheduler.FromCurrentSynchronizationContext() ) are completely unsuitable for use with Parallel.ForEach() .

  • ThreadPool uses a fairly sophisticated algorithm to determine exactly how many threads should execute at any given time. But most importantly, planning a new work item can lead to the creation of a new thread (although not necessarily right away). And since Parallel.ForEach() will always execute some element in the queue, it fully complies with the internal ThreadPool algorithm to determine the number of threads.

Combine, it’s almost impossible to determine how many threads Parallel.ForEach() will use, because it depends on many variables. Both extremes are possible: the cycle will be executed completely synchronously in the current thread and that each element will be launched independently, a newly created thread.

But, as a rule, it should be close to optimal efficiency, and you probably do not need to worry about all these details.

+11
source

Parallel.Foreach does not create new threads or mobilize all threads. It uses a limited number of threads from threadpool and sends tasks for them for parallel execution. In the current implementation, by default, one thread per core is used.

+1
source

I think that is not the case with you. From PATTERNS PARALLEL PROGRAMMING you will see that Parallel.ForEach is really syntactic sugar.

Parallel.ForEach basically comes down to something like this,

 for (int p = 0; p < arrayStrings.Count(); p++) { ThreadPool.QueueUserWorkItem(DoSomething(arrayStrings[p]); } 

ThreadPool takes care of planning. There are some great articles on how the ThreadPool scheduler behaves to some degree if you're interested, but this has nothing to do with TPL.

+1
source

Parallel does not deal with threads at all - it plans TASKS for the task platform. Then it has a scheduler, and the default scheduler is sent to threadpool. This one will try to find the number of threads in goo (better at 4.5 than 4.0), and Threadpool can slowly deploy new threads.

But this is not functoin of parallel.foreach;)

Parallel.ForEach will create any new thread.

It will never be. As I said, it has 1000 foreach, then it poses 10,000 tasks, Point. The Task factory scheduler will do what it has programmed to execute ((you can replace it). Usually the default is yes, slowly new threads will spring up WITHIN REASON.

0
source

Source: https://habr.com/ru/post/917181/


All Articles