I have a question about C#'s worker threads

100 Views Asked by At

In this code, when you use await Task.Delay(5000);, the line Console.WriteLine("START TestSemaPhoreSlims:ID[" + ids + "]... is executed without any delay.

However, when you use Thread.Sleep(5000);, you observe a delay in the logs starting from "START TestSemaPhoreSlims:ID[ID:7] workerThreads>>>2040: times>>>16-06-44". The expected behavior is that the Console.WriteLine statement should execute immediately without any delay.

I hope this clarifies the issue. Let me know if you have any further questions.

public class SemaPhoreTest1s
{
    public SemaPhoreTest1s()
    {
        for (int i = 1; i <= 10; i++)
        {
            int idnums = i;

            Task.Run(() => TestSemaPhoreSlims("ID:" + idnums));
        }

        Console.WriteLine("MAIN THREAD:" + Thread.CurrentThread.ManagedThreadId);

        Console.ReadLine();
    }

    public async void TestSemaPhoreSlims(string ids)
    {
        int workerThreads, completionPortThreads;
        ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);

        Console.WriteLine("START TestSemaPhoreSlims:ID[" + ids + "] workerThreads>>>" + workerThreads + ": times>>>" + DateTime.Now.ToString("HH-mm-ss"));

        Thread.Sleep(5000);
        //await Task.Delay(5000);
    }
}
MAIN THREAD:1  
START TestSemaPhoreSlims:ID\[ID:2\] workerThreads\>\>\>2041: times\>\>\>16-06-43  
START TestSemaPhoreSlims:ID\[ID:1\] workerThreads\>\>\>2041: times\>\>\>16-06-43  
START TestSemaPhoreSlims:ID\[ID:5\] workerThreads\>\>\>2041: times\>\>\>16-06-43  
START TestSemaPhoreSlims:ID\[ID:4\] workerThreads\>\>\>2041: times\>\>\>16-06-43  
START TestSemaPhoreSlims:ID\[ID:3\] workerThreads\>\>\>2041: times\>\>\>16-06-43  
START TestSemaPhoreSlims:ID\[ID:6\] workerThreads\>\>\>2041: times\>\>\>16-06-43  
START TestSemaPhoreSlims:ID\[ID:7\] workerThreads\>\>\>2040: times\>\>\>16-06-44  
START TestSemaPhoreSlims:ID\[ID:8\] workerThreads\>\>\>2039: times\>\>\>16-06-45  
START TestSemaPhoreSlims:ID\[ID:9\] workerThreads\>\>\>2038: times\>\>\>16-06-46  
START TestSemaPhoreSlims:ID\[ID:10\] workerThreads\>\>\>2037: times\>\>\>16-06-47
1

There are 1 best solutions below

0
Sir Rufo On

The ThreadPool starts with an amount of worker threads defined. You can get that information by calling ThreadPool.GetMinThreads method, which returns the minimum for worker- and completionPort threads.

The thread pool increases the number of worker threads while running but it takes some time to do so. You can watch this, when you repeat the code again and again within the same process. Also the thread pool will kill worker threads after an amount of time when they are not used.

To get all tasks running from the start set the minimum worker threads to the value you are satisfied with (here 10 will be enough).

// set before you run your code
ThreadPool.SetMinThreads( 10, 1 );

Now every task should run as you expected.

When you want to watch how the number of worker threads changes you can print out the Threadpool.ThreadCount value.


Why does this not happen with Task.Delay?

Because with Task.Delay there is no Thread (for that delay). Behind the scenes there is a state machine that will be activated again from the Scheduler when the delay is over.