Why is there a “hidden” 1st timeout in the parallel task library for scheduling tasks under certain conditions?

My laptop has 2 logical processors, and I came across a scenario where, if I plan 2 tasks that take more than 1 second, without designating them long-term, subsequent tasks start in 1 second. Is it possible to change this timeout?

I know that ordinary tasks should be short - much shorter than a second, if possible - I'm just wondering if I see a hard-coded TPL behavior or if I can influence this behavior in any other way, it works.

This Console application method should demonstrate behavior for a machine with any number of processors:

static void Main(string[] args) { var timer = new Stopwatch(); timer.Start(); int numberOfTasks = Environment.ProcessorCount; var rudeTasks = new List<Task>(); var shortTasks = new List<Task>(); for (int index = 0; index < numberOfTasks; index++) { int capturedIndex = index; rudeTasks.Add(Task.Factory.StartNew(() => { Console.WriteLine("Starting rude task {0} at {1}ms", capturedIndex, timer.ElapsedMilliseconds); Thread.Sleep(5000); })); } for (int index = 0; index < numberOfTasks; index++) { int capturedIndex = index; shortTasks.Add(Task.Factory.StartNew(() => { Console.WriteLine("Short-running task {0} running at {1}ms", capturedIndex, timer.ElapsedMilliseconds); })); } Task.WaitAll(shortTasks.ToArray()); Console.WriteLine("Finished waiting for short tasks at {0}ms", timer.ElapsedMilliseconds); Task.WaitAll(rudeTasks.ToArray()); Console.WriteLine("Finished waiting for rude tasks at {0}ms", timer.ElapsedMilliseconds); Console.ReadLine(); } 

Here is the output of the application on my 2-processor laptop:

 Starting rude task 0 at 2ms Starting rude task 1 at 2ms Short-running task 0 running at 1002ms Short-running task 1 running at 1002ms Finished waiting for short tasks at 1002ms Finished waiting for rude tasks at 5004ms Press any key to continue . . . 

Rows:

 Short-running task 0 running at 1002ms Short-running task 1 running at 1002ms 

indicate that there is a 1-second timeout or something similar that allows you to perform shorter tasks on "rough" tasks. This is what I am asking.

+4
source share
3 answers

The behavior that you see is not TPL, it is typical for the default TPL scheduler . The scheduler is trying to increase the number of threads, so those that work do not "dig out" the processor and do not drown others. It also helps to avoid deadlock situations if two start up and wait for the tasks themselves.

If you want to change the planning behavior, you may need to study the implementation of your own TaskScheduler .

+4
source

This is standard behavior for the thread scheduler. He is trying to keep the number of active threads equal to the number of cores. But it can’t do the job very well when your tasks do a lot of blocking rather than working. Sleep in your case. Twice per second, it allows you to start another thread to try to work the lag. It looks like you have a dual core processor.

The correct workaround is to use TaskCreationOptions.LongRunning, so the scheduler uses a regular thread instead of a threadpool thread. The wrong workaround is to use ThreadPool.SetMinThreads. But you may need to focus on doing real work in your tasks; Sleep () is not a good imitation of this.

+4
source

The problem is that the scheduler starts new tasks when he tries to determine how long the task has been running. You can tell TPL that the task takes a long time to complete as a task parameter:

 for (int index = 0; index < numberOfTasks; index++) { int capturedIndex = index; rudeTasks.Add(Task.Factory.StartNew(() => { Console.WriteLine("Starting rude task {0} at {1}ms", capturedIndex, timer.ElapsedMilliseconds); Thread.Sleep(3000); }, TaskCreationOptions.LongRunning)); } 

Result:

 Starting rude task 0 at 11ms Starting rude task 1 at 13ms Starting rude task 2 at 15ms Starting rude task 3 at 19ms Short-running task 0 running at 45ms Short-running task 1 running at 45ms Short-running task 2 running at 45ms Short-running task 3 running at 45ms Finished waiting for short tasks at 46ms Finished waiting for rude tasks at 3019ms 
+1
source

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


All Articles