Why Thread.Sleep affects creation of new Tasks?

2019-01-15 20:34发布

问题:

private static void Main(string[] args)
{
    for (int i = 0; i < 1000; i++)
    {
        Task.Factory.StartNew(() =>
        {
            Thread.Sleep(1000);
            Console.WriteLine("hej");
            Thread.Sleep(10000);
        });    
    }
    Console.ReadLine();
}

Why this code won't print 1000 times "hej" after one second? Why Thread.Sleep(10000) has an impact on code behavior?

回答1:

Factory.StartNew effectively delegates the work to ThreadPool.

Threadpool will create number of threads immediately to respond the request as long as threads count is less than or equal to processor count. Once it reaches processor count, threadpool will stop creating new threads immediately. That makes sense, because creating number of threads more than processor count introduces Thread scheduling overhead and returns nothing.

Instead it will throttle the creation of threads. It waits for 500 ms to see if any work still pending and no threads to process the request. If pending works are there, it will introduce a new thread(only one). This process keeps on going as long as you have enough works to do.

When work queue's traffic is cleared, threadpool will destroy the threads. And above mentioned process keeps on going.

Also, There is a max limit for number of threads threadpool can run simultaneously. If you hit that, threadpool will stop creating more threads and wait for previous work items to complete, So that it can reuse the existing thread.

That's not the end of story, It is convoluted! These are few decisions taken by ThreadPool.

I hope now that will be clear why you see what you see.



回答2:

There are a multitude of factors that would alter the result.

Some being (but not limited to):

  • The inherent time for the iteration of the loop
  • The size of the thread pool
  • Thread management overhead


回答3:

The way you code behaves is intended behaviour. You wait 1000 milliseconds to print hej and after printing you do Thread.sleep for another 10000 millesconds. If you want to print 1000 times hej after one second remove Thread.sleep(10000).