Meredith
Meredith

Reputation: 940

Need help understanding .net ThreadPool

I am trying to understand what ThreadPool does, I have this .NET example:

class Program
{
    static void Main()
    {
        int c = 2;

        // Use AutoResetEvent for thread management

        AutoResetEvent[] arr = new AutoResetEvent[50];

        for (int i = 0; i < arr.Length; ++i)
        {
            arr[i] = new AutoResetEvent(false);
        }

        // Set the number of minimum threads
        ThreadPool.SetMinThreads(c, 4);

        // Enqueue 50 work items that run the code in this delegate function
        for (int i = 0; i < arr.Length; i++)
        {
            ThreadPool.QueueUserWorkItem(delegate(object o)
            {
                Thread.Sleep(100);
                arr[(int)o].Set(); // Signals completion

            }, i);
        }

        // Wait for all tasks to complete
        WaitHandle.WaitAll(arr);
    }
}

Does this run 50 "tasks", in groups of 2 (int c) until they all finish? Or I am not understanding what it really does.

Upvotes: 3

Views: 1140

Answers (4)

KeithS
KeithS

Reputation: 71565

Background: The normal method by which the .NET thread pool manages threads can be cumbersome. It works well to limit problems caused by resource contention, but it does so at the expense of how quickly threads are created. To increase the performance of worker threading with the thread pool, the designers allowed for a mechanism that allows a certain small number of threads to be created without going through the queue process.

SetMinThreads() specifies the number of threads that should simply be created "on demand", that is, simply started up without any checks on the current thread count or queueing to throttle up slowly.

What will happen is that the framework will create the first two threads immediately, as if you'd manually set 'em up and kicked 'em off with Thread.Start. Beyond that, up to the current MaxThreads count, the framework will begin to queue up requests for worker threads and start them at a specified interval (by default, 250ms, I believe this can also be configured) to avoid resource collision. The reason for this is that if you imagine a looped behavior of starting a thread that accesses a resource, does some calculation, then writes the result somewhere else, you can see how 5 threads starting up near-simultaneously would cause a logjam attempting to get to that first resource. At the MaxThreads threshold, the queue is stopped; no new threads are created until one finishes.

So, just by nature of your code, 50 separate worker tasks will be scheduled, but not all 50 will be running at the same time; the runtime will allow two to start immediately, then wait 250ms or until one ends before kicking off the next. Because the threads will execute and terminate in less than 250ms, you're unlikely to see more than 2 worker threads executing at once; the wait before creating that third one will never occur because an "unrestricted" worker thread will free up first and the one that was waiting is kicked off before its wait time expires, then the clock is reset with the next one.

Upvotes: 0

David Hoerster
David Hoerster

Reputation: 28701

From the MSDN documentation on SetMinThreads:

When demand is low, the actual number of thread pool threads can fall below the minimum values.

So the value that you specify doesn't guarantee that 2 worker threads will work on the queued items. It could be 1 worker thread (since you're queueing them up in a loop, it may finish before the next one gets queued up), or it could use more based upon the system resources and the amount of work that has to be done.

If you really want to see what's going on, check out a tool like Process Monitor. You can monitor your process' thread creation and track when they're created, destroyed, etc. It will really help you realize what your application (and the underlying framework) is doing.

Hope this helps.

Upvotes: 0

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391276

By setting the minimum number of threads, the only thing you're asking the .NET runtime to do is to please allocate at least 2 threads for the thread pool. You're not asking it to limit itself to only 2.

As such, there is no guarantee on how many threads in particular your program will use for this. It depends on your system and a lot of other factors.

A simple test I made (minor change to your program to just keep track of simultaneous threads entering the sleep call) maxed out at 4 in one run, 3 in another, 7 in another, 10 in another, etc.

You really shouldn't need to change the thread pool size.

What are you trying to accomplish?

Upvotes: 1

Joe
Joe

Reputation: 11637

If you've got a bit of time, I would really recommend this read:

http://www.albahari.com/threading/

It's an excellent read that lays the foundation and works it's way from basic threading to parallel programming. I'd recommend you to have a basic grasp of the first two chapters before trying to modify threadpool code! :)

Upvotes: 3

Related Questions