Applications that use many short-lived threads or maintain large numbers of concurrent threads can suffer performance degradation because of the overhead associated with the creation, operation, and destruction of threads. In addition, it's common in multithreaded systems for threads to sit idle a large portion of the time while they wait for the appropriate conditions to trigger their execution. Use of a thread pool provides a common solution to improve the scalability, efficiency, and performance of multithreaded systems.
The .NET Framework provides a simple thread-pool implementation accessible through the static members of the ThreadPool class. The QueueUserWorkItem method allows you to execute a method using a thread-pool thread by placing a work item on a queue. The work item is represented by a WaitCallback delegate instance that references the method you want to execute. As a thread from the thread pool becomes available, it takes the next work item from the queue and executes it. The thread carries out the work assigned to it, and when it's finished, instead of terminating, the thread returns to the thread pool and takes the next work item from the work queue.
Use of the runtime's thread pool simplifies multithreaded programming dramatically; however, be aware that the implementation is a simple, general- purpose thread pool. Before deciding to use the thread pool, consider the following points:
-
The runtime host determines the maximum number of threads allocated to the thread pool; you can't change this maximum number using configuration parameters or from within managed code. The default limit is 25 threads per CPU in your system. The maximum number of threads in the thread pool does not limit the number of items that can be waiting in the queue. -
As well as allowing you to use the thread pool to execute code directly, the runtime uses the thread pool for many purposes internally. All of these uses can lead to heavy contention for the thread-pool threads, meaning that the work queue can become very long. Although the work queue's maximum length is limited only by the amount of memory available to the runtime's process, an excessively long queue will result in long delays before queued work items are executed. -
You shouldn't use the thread pool to execute long-running processes. The limited number of threads in the thread pool means that a handful of threads tied up with long-running processes can have a significant effect on the overall performance of the thread pool. Specifically, you should avoid putting thread-pool threads to sleep for any length of time. -
You have no control over the scheduling of thread-pool threads, nor can you prioritize work items. The thread pool handles each work item in the sequence in which you add it to the work queue. -
Once a work item is queued, it can't be cancelled or stopped.
The following example demonstrates the use of the ThreadPool class to execute a method named DisplayMessage. The example passes DisplayMessage to the thread pool twice, first with no arguments, and then with a MessageInfo object, which allows you to control which message the new thread will display.
using System; using System.Threading; // A class used to pass data to the DisplayMessage method when it is // executed using the thread pool. public class MessageInfo { private int iterations; private string message; // A constructor that takes configuration settings for the thread. public MessageInfo(int iterations, string message) { this.iterations = iterations; this.message = message; } // Properties to retrieve configuration settings. public int Iterations { get { return iterations; } } public string Message { get { return message; } } } public class ThreadPoolExample { // Displays a message to the console. public static void DisplayMessage(object state) { // Cast the state argument to a MessageInfo object. MessageInfo config = state as MessageInfo; // If the config argument is null, no arguments were passed to // the ThreadPool.QueueUserWorkItem method, use default values. if (config == null) { // Display a fixed message to the console 3 times. for (int count = 0; count < 3; count++) { Console.WriteLine("A thread pool example."); // Sleep for the purpose of demonstration. Avoid sleeping // on thread-pool threads in real applications. Thread.Sleep(1000); } } else { // Display the specified message the specified number of times. for (int count = 0; count < config.Iterations; count++) { Console.WriteLine(config.Message); // Sleep for the purpose of demonstration. Avoid sleeping // on thread-pool threads in real applications. Thread.Sleep(1000); } } } public static void Main() { // Create a delegate instance to enable us to pass the // DisplayMessage method to the thread pool for execution. WaitCallback workMethod = new WaitCallback(ThreadPoolExample.DisplayMessage); // Execute DisplayMessage using the thread pool and no arguments. ThreadPool.QueueUserWorkItem(workMethod); // Execute DisplayMessage using the thread pool and providing a // MessageInfo object to pass to the DisplayMessage method. MessageInfo info = new MessageInfo(5, "A thread pool example with arguments."); ThreadPool.QueueUserWorkItem(workMethod, info); // Wait to continue. Console.WriteLine("Main method complete. Press Enter."); Console.ReadLine(); } }
No comments:
Post a Comment