Bewerken

Share via


ThreadPool Class

Definition

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.

public ref class ThreadPool abstract sealed
public ref class ThreadPool sealed
public static class ThreadPool
public sealed class ThreadPool
type ThreadPool = class
Public Class ThreadPool
Public NotInheritable Class ThreadPool
Inheritance
ThreadPool

Examples

In the following example, the main application thread queues a method named ThreadProc to execute on a thread pool thread, sleeps for one second, and then exits. The ThreadProc method simply displays a message.

using namespace System;
using namespace System::Threading;

ref class Example
{
public:

   // This thread procedure performs the task.
   static void ThreadProc(Object^ stateInfo)
   {
      
      // No state object was passed to QueueUserWorkItem, so stateInfo is 0.
      Console::WriteLine( "Hello from the thread pool." );
   }
};

int main()
{
   // Queue the task.
   ThreadPool::QueueUserWorkItem(gcnew WaitCallback(Example::ThreadProc));

   Console::WriteLine("Main thread does some work, then sleeps.");
   
   Thread::Sleep(1000);
   Console::WriteLine("Main thread exits.");
   return 0;
}
// The example displays output like the following:
//       Main thread does some work, then sleeps.
//       Hello from the thread pool.
//       Main thread exits.
using System;
using System.Threading;

public class Example 
{
    public static void Main() 
    {
        // Queue the task.
        ThreadPool.QueueUserWorkItem(ThreadProc);
        Console.WriteLine("Main thread does some work, then sleeps.");
        Thread.Sleep(1000);

        Console.WriteLine("Main thread exits.");
    }

    // This thread procedure performs the task.
    static void ThreadProc(Object stateInfo) 
    {
        // No state object was passed to QueueUserWorkItem, so stateInfo is null.
        Console.WriteLine("Hello from the thread pool.");
    }
}
// The example displays output like the following:
//       Main thread does some work, then sleeps.
//       Hello from the thread pool.
//       Main thread exits.
Imports System.Threading

Public Module Example
    Public Sub Main()
        ' Queue the work for execution.
        ThreadPool.QueueUserWorkItem(AddressOf ThreadProc)
        
        Console.WriteLine("Main thread does some work, then sleeps.")

        Thread.Sleep(1000)

        Console.WriteLine("Main thread exits.")
    End Sub

    ' This thread procedure performs the task.
    Sub ThreadProc(stateInfo As Object)
        ' No state object was passed to QueueUserWorkItem, so stateInfo is null.
        Console.WriteLine("Hello from the thread pool.")
    End Sub
End Module
' The example displays output like the following:
'       Main thread does some work, then sleeps.
'       Hello from the thread pool.
'       Main thread exits.

If you comment out the call to the Thread.Sleep method, the main thread exits before method runs on the thread pool thread. The thread pool uses background threads, which do not keep the application running if all foreground threads have terminated. (This is a simple example of a race condition.)

Remarks

Many applications create threads that spend a great deal of time in the sleeping state, waiting for an event to occur. Other threads might enter a sleeping state only to be awakened periodically to poll for a change or update status information. The thread pool enables you to use threads more efficiently by providing your application with a pool of worker threads that are managed by the system. Examples of operations that use thread pool threads include the following:

  • When you create a Task or Task<TResult> object to perform some task asynchronously, by default the task is scheduled to run on a thread pool thread.

  • Asynchronous timers use the thread pool. Thread pool threads execute callbacks from the System.Threading.Timer class and raise events from the System.Timers.Timer class.

  • When you use registered wait handles, a system thread monitors the status of the wait handles. When a wait operation completes, a worker thread from the thread pool executes the corresponding callback function.

  • When you call the QueueUserWorkItem method to queue a method for execution on a thread pool thread. You do this by passing the method a WaitCallback delegate. The delegate has the signature

    void WaitCallback(Object state)
    
    Sub WaitCallback(state As Object)
    

    where state is an object that contains data to be used by the delegate. The actual data can be passed to the delegate by calling the QueueUserWorkItem(WaitCallback, Object) method.

Note

The threads in the managed thread pool are background threads. That is, their IsBackground properties are true. This means that a ThreadPool thread will not keep an application running after all foreground threads have exited.

Important

When the thread pool reuses a thread, it does not clear the data in thread local storage or in fields that are marked with the ThreadStaticAttribute attribute. Therefore, when a method examines thread local storage or fields that are marked with the ThreadStaticAttribute attribute, the values it finds might be left over from an earlier use of the thread pool thread.

You can also queue work items that are not related to a wait operation to the thread pool. To request that a work item be handled by a thread in the thread pool, call the QueueUserWorkItem method. This method takes as a parameter a reference to the method or delegate that will be called by the thread selected from the thread pool. There is no way to cancel a work item after it has been queued.

Timer-queue timers and registered wait operations also use the thread pool. Their callback functions are queued to the thread pool.

There is one thread pool per process. Beginning with the .NET Framework 4, the default size of the thread pool for a process depends on several factors, such as the size of the virtual address space. A process can call the GetMaxThreads method to determine the number of threads. The number of threads in the thread pool can be changed by using the SetMaxThreads method. Each thread uses the default stack size and runs at the default priority.

Note

Unmanaged code that hosts the .NET Framework can change the size of the thread pool by using the CorSetMaxThreads function, defined in the mscoree.h file.

The thread pool provides new worker threads or I/O completion threads on demand until it reaches the maximum for each category. When a maximum is reached, the thread pool can create additional threads in that category or wait until some tasks complete. Beginning with the .NET Framework 4, the thread pool creates and destroys worker threads in order to optimize throughput, which is defined as the number of tasks that complete per unit of time. Too few threads might not make optimal use of available resources, whereas too many threads could increase resource contention.

Note

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

You can use the GetMinThreads method to obtain these minimum values.

Caution

You can use the SetMinThreads method to increase the minimum number of threads. However, unnecessarily increasing these values can cause performance problems. If too many tasks start at the same time, all of them might appear to be slow. In most cases the thread pool will perform better with its own algorithm for allocating threads.

Properties

CompletedWorkItemCount

Gets the number of work items that have been processed so far.

PendingWorkItemCount

Gets the number of work items that are currently queued to be processed.

ThreadCount

Gets the number of thread pool threads that currently exist.

Methods

BindHandle(IntPtr)
Obsolete.
Obsolete.

Binds an operating system handle to the ThreadPool.

BindHandle(SafeHandle)

Binds an operating system handle to the ThreadPool.

GetAvailableThreads(Int32, Int32)

Retrieves the difference between the maximum number of thread pool threads returned by the GetMaxThreads(Int32, Int32) method, and the number currently active.

GetMaxThreads(Int32, Int32)

Retrieves the number of requests to the thread pool that can be active concurrently. All requests above that number remain queued until thread pool threads become available.

GetMinThreads(Int32, Int32)

Retrieves the minimum number of threads the thread pool creates on demand, as new requests are made, before switching to an algorithm for managing thread creation and destruction.

QueueUserWorkItem(WaitCallback, Object)

Queues a method for execution, and specifies an object containing data to be used by the method. The method executes when a thread pool thread becomes available.

QueueUserWorkItem(WaitCallback)

Queues a method for execution. The method executes when a thread pool thread becomes available.

QueueUserWorkItem<TState>(Action<TState>, TState, Boolean)

Queues a method specified by an Action<T> delegate for execution, and provides data to be used by the method. The method executes when a thread pool thread becomes available.

RegisterWaitForSingleObject(WaitHandle, WaitOrTimerCallback, Object, Int32, Boolean)

Registers a delegate to wait for a WaitHandle, specifying a 32-bit signed integer for the time-out in milliseconds.

RegisterWaitForSingleObject(WaitHandle, WaitOrTimerCallback, Object, Int64, Boolean)

Registers a delegate to wait for a WaitHandle, specifying a 64-bit signed integer for the time-out in milliseconds.

RegisterWaitForSingleObject(WaitHandle, WaitOrTimerCallback, Object, TimeSpan, Boolean)

Registers a delegate to wait for a WaitHandle, specifying a TimeSpan value for the time-out.

RegisterWaitForSingleObject(WaitHandle, WaitOrTimerCallback, Object, UInt32, Boolean)

Registers a delegate to wait for a WaitHandle, specifying a 32-bit unsigned integer for the time-out in milliseconds.

SetMaxThreads(Int32, Int32)

Sets the number of requests to the thread pool that can be active concurrently. All requests above that number remain queued until thread pool threads become available.

SetMinThreads(Int32, Int32)

Sets the minimum number of threads the thread pool creates on demand, as new requests are made, before switching to an algorithm for managing thread creation and destruction.

UnsafeQueueNativeOverlapped(NativeOverlapped*)

Queues an overlapped I/O operation for execution.

UnsafeQueueUserWorkItem(IThreadPoolWorkItem, Boolean)

Queues the specified work item object to the thread pool.

UnsafeQueueUserWorkItem(WaitCallback, Object)

Queues the specified delegate to the thread pool, but does not propagate the calling stack to the worker thread.

UnsafeQueueUserWorkItem<TState>(Action<TState>, TState, Boolean)

Queues a method specified by an Action<T> delegate for execution, and specifies an object containing data to be used by the method. The method executes when a thread pool thread becomes available.

UnsafeRegisterWaitForSingleObject(WaitHandle, WaitOrTimerCallback, Object, Int32, Boolean)

Registers a delegate to wait for a WaitHandle, using a 32-bit signed integer for the time-out in milliseconds. This method does not propagate the calling stack to the worker thread.

UnsafeRegisterWaitForSingleObject(WaitHandle, WaitOrTimerCallback, Object, Int64, Boolean)

Registers a delegate to wait for a WaitHandle, specifying a 64-bit signed integer for the time-out in milliseconds. This method does not propagate the calling stack to the worker thread.

UnsafeRegisterWaitForSingleObject(WaitHandle, WaitOrTimerCallback, Object, TimeSpan, Boolean)

Registers a delegate to wait for a WaitHandle, specifying a TimeSpan value for the time-out. This method does not propagate the calling stack to the worker thread.

UnsafeRegisterWaitForSingleObject(WaitHandle, WaitOrTimerCallback, Object, UInt32, Boolean)

Registers a delegate to wait for a WaitHandle, specifying a 32-bit unsigned integer for the time-out in milliseconds. This method does not propagate the calling stack to the worker thread.

Applies to

Thread Safety

This type is thread safe.

See also