Your application will be creating many threads from the thread pool. When creating a thread from this pool, you want to be informed as to whether a thread in the pool is available or if none are available, and the request for a new thread will have to be queued. Basically, you want to know whether a thread is available for immediate use from the thread pool.
Use the
ThreadPool.GetAvailableThreads
method to get the
number of worker threads currently available in the
ThreadPool
to determine whether you should queue
another request to launch another thread via
ThreadPool.QueueUserWorkItem
or take an alternate
action. The Main
method calls a method
(SpawnManyThreads
) to spawn lots of threads to do
work in the ThreadPool
, then waits for a bit to
simulate processing:
public class TestThreads { public static void Main( ) { SpawnManyThreads( ); // have to wait here or the background threads in the thread // pool would not run before the main thread exits. Console.WriteLine("Main Thread waiting to complete..."); Thread.Sleep(2000); Console.WriteLine("Main Thread completing..."); }
The
SpawnManyThreads
method launches threads and
pauses between each launch to allow the ThreadPool
to register the request and act upon it. The
isThreadAvailable
method is called with the parameter set to true
to
determine whether there is a worker thread available for use in the
ThreadPool
:
public static bool SpawnManyThreads( ) { try { for(int i=0;i<500;i++) { // have to wait or threadpool never gives out threads to // requests Thread.Sleep(100); // check to see if worker threads are available in the pool if(true == isThreadAvailable(true)) { // launch thread if queue isn't full Console.WriteLine("Worker Thread was available..."); ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc),i); } else Console.WriteLine("Worker Thread was NOT available..."); } } catch(Exception e) { Console.WriteLine(e.ToString( )); return false; } return true; }
The isThreadAvailable
method calls
ThreadPool.GetAvailableThreads
to determine
whether the ThreadPool
has any available worker
threads left. If you pass false
as the
checkWorkerThreads
parameter, it also sees whether
there are any completion port threads available. The
GetAvailableThreads
method compares the current
number of threads allocated from the pool against the maximum
ThreadPool
threads. The worker thread maximum is
25 per CPU, and the completion port thread maximum is 1,000 total,
regardless of CPUs on v1.1 of the
CLR:
public static bool isThreadAvailable(bool checkWorkerThreads) { int workerThreads = 0; int completionPortThreads = 0; // get available threads ThreadPool.GetAvailableThreads(out workerThreads,out completionPortThreads); // indicate how many work threads are available Console.WriteLine("{0} worker threads available in thread pool.", workerThreads); if(checkWorkerThreads) { if(workerThreads > 0) return true; } else // check completion port threads { if(completionPortThreads > 0) return true; } return false; }
This is a simple method to call in a threaded fashion:
static void ThreadProc(Object stateInfo) { // show we did something with this thread Console.WriteLine("Thread {0} running...",stateInfo); Thread.Sleep(1000); } }
The ThreadPool
is a great way to perform
background tasks without having to manage all aspects of the thread
yourself. It can be handy to know when the
ThreadPool
itself is going to become a bottleneck
to your application, and the
GetAvailableThreads
method can help you. However, you might want to check your
application design if you are consistently using this many threads as
you might be losing performance due to contention or context
switching. Queuing up work when the ThreadPool
is
full simply queues it up for execution once one of the threads comes
free; the request isn’t lost, just postponed.