Intro

On one of the job interviews I have been asked about ThreadPool, after my answer (which was 100% correct) interviewer decided to give me a small test.

Code

He gave me a short program:

public class Program
{
    private static int _value;

    public static void Main(string[] args)
    {
        for (var i = 0; i < 50; i++)
        {
            ThreadPool.QueueUserWorkItem(state =>
            {
                Console.WriteLine(_value++);
                Thread.Sleep(20);
            });
        }

        Console.ReadLine();
    }
}

He wanted to know what will be the output. I have said it will output a list of numbers with values between 0 and 50 with duplicates. And I doubt there will be 50 in the end because of issue with shared _value field.

It was a correct answer.

Then my interviewer changed the code to:

public class Program
{
    [ThreadStatic]
    private static int _value;

    public static void Main(string[] args)
    {
        for (var i = 0; i < 50; i++)
        {
            ThreadPool.QueueUserWorkItem(state =>
            {
                Console.WriteLine(_value++);
                Thread.Sleep(20);
            });
        }

        Console.ReadLine();
    }
}

The question was the same. I answered that there will be a set of numbers, with lots of duplicates and the maximum number should be less than 50/number of threads in thread pool. I've been almost correct.

ThreadPool provides a pool of threads that can be used to execute tasks, post work items, process asynchronous I/O, wait on behalf of other threads, and process timers. The thread pool (by design) keeps the threads alive between calls. This means that the ThreadStatic variables will persist between calls to QueueUserWorkItem. But this behavior is also something you should not count on. The ThreadPool will (eventually, at its discretion) release threads back and let them end, and construct new threads as needed.

So my assumption was wrong. Depending on environment, the last example may give a very different results. That is, ThreadStatic and the ThreadPool aren't always a great combination - you just don't necessarily have enough control (since the ThreadPool manages the threads) to really take advantage and get benefits from ThreadStatic variables.

Summary

You'll never know whether two work items will be on the same thread, different threads, and whether the ThreadStatic variable should be (re)initialized, etc.


;