This note is excerpted from: https://www.cnblogs.com/zhili/archive/2012/07/18/ThreadPool.html Record the learning process for future reference.
I. thread pool Foundation
First of all, it takes a lot of time to create and destroy threads. Second, too many threads also waste memory resources. Therefore, creating too many threads through Thread class is detrimental to performance. To improve this
The thread pool is introduced in. NET.
The representation of thread pool image is a collection of threads used in an application (that is, the place where threads are put, so that threads can be managed in one place).
During CLR initialization, there are no threads in the thread pool. Internally, the thread pool maintains an operation request queue. When the application wants to perform an asynchronous operation, it calls a method to put a task into the thread pool
In the queue of, the thread pool code extracts the task from the queue and delegates the task to a thread pool thread for execution. When the thread pool thread completes the task, the thread will not be destroyed, but will return to the thread pool and wait for a response
A request. Because the thread is not destroyed, the performance loss caused by thread creation can be avoided.
MSDN statement:
"Thread pool is often used in server applications. Each new requirement is assigned to a thread in a thread pool, so that the requirement can be executed asynchronously without hindering the main thread or delaying the processing of subsequent requirements."
Note: threads created through the thread pool are background threads by default, and the priority is Normal by default.
2. Asynchronous implementation through worker threads of thread pool
2.1 method of creating worker thread
public static bool QueueUserWorkItem (WaitCallback callback);
public static bool QueueUserWorkItem(WaitCallback callback, Object state);
These two methods add a work item and an optional status data to the queue of thread pool, and then the two methods will return immediately.
The work item is actually a method identified by the callback parameter, which will be executed by the thread pool thread. The callback method written at the same time must match the System.Threading.WaitCallback delegate type, defined as:
public delegate void WaitCallback(Object state);
The following shows how to implement asynchronous calls through thread pool threads:
class Program { static void Main(string[] args) { #region Asynchronous implementation through worker threads of thread pool //Set the maximum number of worker threads in the thread pool to 1000, I/O The maximum number of threads is 1000. ThreadPool.SetMaxThreads(1000, 1000); Console.WriteLine("Main thread: queue an asynchronous method."); PrintMessage("Main thread start."); //Add the work item to the queue, and the thread pool will use the worker thread to execute the callback method. ThreadPool.QueueUserWorkItem(AsyncMethod); Console.Read(); #endregion } /// <summary> /// Print thread pool information /// </summary> /// <param name="data"></param> private static void PrintMessage(string data) { // Get the number of worker threads available in the thread pool and I/O Number of threads ThreadPool.GetAvailableThreads(out int workThreadNumber, out int ioThreadNumber); Console.WriteLine("{0}\n CurrentThreadId is:{1}\n CurrentThread is background:{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is:{4}\n", data, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsBackground.ToString(), workThreadNumber.ToString(), ioThreadNumber.ToString()); } /// <summary> /// Asynchronous method: must match WaitCallback Entrust /// </summary> /// <param name="state"></param> private static void AsyncMethod(object state) { Thread.Sleep(1000); PrintMessage("Asynchoronous method."); Console.WriteLine("Asynchoronous thread has worked."); } }
The operation results are as follows:
From the result, we can see that there is one less worker thread available in the thread pool to execute the callback method.
The ThreadPool.QueueUserWorkItem(WaitCallback callback,Object state) method can pass the object object as a parameter to the callback function, using the method and
ThreadPool.QueueUserWorkItem(WaitCallback callback) is similar. It is not listed here.
2.2 collaborative cancellation
The. NET Framework provides a cancellation mode, which is collaborative. In order to cancel an operation, you must first create a system. Threading. Cancelationtokensource object.
The following code demonstrates the use of collaborative cancellation, which is mainly used to stop counting when the user clicks the Enter key on the console.
class Program { static void Main(string[] args) { #region Collaborative cancellation ThreadPool.SetMaxThreads(1000, 1000); Console.WriteLine("Main thread run."); PrintMessage("Start"); Run(); Console.ReadKey(); #endregion } /// <summary> /// Print thread pool information /// </summary> /// <param name="data"></param> private static void PrintMessage(string data) { //Get the number of worker threads available in the thread pool and I/O Number of threads ThreadPool.GetAvailableThreads(out int workThreadNumber, out int ioThreadNumber); Console.WriteLine("{0}\n CurrentThreadId is:{1}\n CurrentThread is background:{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is:{4}\n", data, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsBackground.ToString(), workThreadNumber.ToString(), ioThreadNumber.ToString()); } /// <summary> /// Run worker thread(Include collaborative cancellation) /// </summary> private static void Run() { CancellationTokenSource cts = new CancellationTokenSource(); //Here is the use. Lambda The expression is written in the same way. //ThreadPool.QueueUserWorkItem(obj => Count(cts.Token, 1000)); ThreadPool.QueueUserWorkItem(Callback, cts.Token); Console.WriteLine("Press enter key to cancel the operation.\n"); Console.ReadLine(); //Communicate cancellation request cts.Cancel(); } /// <summary> /// Callback function /// </summary> /// <param name="state"></param> private static void Callback(object state) { Thread.Sleep(1000); PrintMessage("Asynchoronous method start."); CancellationToken token = (CancellationToken)state; Count(token, 1000); } /// <summary> /// Count /// </summary> /// <param name="token"></param> /// <param name="countTo"></param> private static void Count(CancellationToken token, int countTo) { for (int i = 1; i <= countTo; i++) { if (token.IsCancellationRequested) { Console.WriteLine("Count is canceled."); break; } Console.WriteLine(i); Thread.Sleep(300); } Console.WriteLine("Count has done."); } }
The operation results are as follows:
III. asynchronous implementation by delegation
Terminology involved -- asynchronous programming model:
APM asynchronous programming model
EAP event based asynchronous pattern
Task based asynchronous pattern
It's very convenient to start the worker thread by calling the QueueUserWorkItem method of ThreadPool, but the delegate WaitCallback points to a method with one parameter and no return value. If we are in actual operation
You need to have a return value, or you need to have multiple parameters, which is difficult to achieve in this way. In order to solve this problem, we can establish the working thread through delegation.
The following code demonstrates using delegation to implement asynchrony:
class Program { //Using delegation to realize asynchrony is using asynchronous programming model APM. private delegate string ThreadDelegate(); static void Main(string[] args) { #region Asynchronous with delegation ThreadPool.SetMaxThreads(1000, 1000); PrintMessage("Main thread start."); //Instantiation delegation ThreadDelegate threadDelegate = new ThreadDelegate(AsyncMethod); //Asynchronous call delegate IAsyncResult result = threadDelegate.BeginInvoke(null, null); //Get results and print string returnData = threadDelegate.EndInvoke(result); Console.WriteLine(returnData); Console.ReadLine(); #endregion } /// <summary> /// Asynchronous method /// </summary> /// <returns></returns> private static string AsyncMethod() { Thread.Sleep(1000); PrintMessage("Asynchoronous method."); return "Method has completed."; } }
The operation results are as follows:
IV. tasks
Similarly, tasks are introduced to solve the problem of restriction in ThreadPool.QueueUserWorkItem.
The following code demonstrates asynchronous implementation through tasks:
4.1 use tasks to achieve asynchrony
class Program { static void Main(string[] args) { #region Asynchronous with tasks ThreadPool.SetMaxThreads(1000, 1000); PrintMessage("Main thread start."); //Call constructor to create Task object Task<int> task = new Task<int>(n => AsyncMethod((int)n), 10); //Start task task.Start(); //Wait for the task to complete task.Wait(); Console.WriteLine("The method result is: " + task.Result); Console.ReadLine(); #endregion } /// <summary> /// Asynchronous method /// </summary> /// <param name="n"></param> /// <returns></returns> private static int AsyncMethod(int n) { Thread.Sleep(1000); PrintMessage("Asynchoronous method."); int sum = 0; for (int i = 1; i < n; i++) { //Operation overflow check checked { sum += i; } } return sum; } }
The operation results are as follows:
4.2 cancel task
If you want to cancel the task, you can also cancel it by cancelationtokensource object.
The following code shows how to cancel a task:
class Program { static void Main(string[] args) { #region Cancel tasks ThreadPool.SetMaxThreads(1000, 1000); PrintMessage("Main thread start."); CancellationTokenSource cts = new CancellationTokenSource(); //Call constructor to create Task Object, changing a CancellationToken Pass to Task Constructor to Task and CancellationToken Connect. Task<int> task = new Task<int>(n => AsyncMethod(cts.Token, (int)n), 10); //Start task task.Start(); //Delay cancel task Thread.Sleep(3000); //Cancel tasks cts.Cancel(); Console.WriteLine("The method result is: " + task.Result); Console.ReadLine(); #endregion } /// <summary> /// Asynchronous method /// </summary> /// <param name="ct"></param> /// <param name="n"></param> /// <returns></returns> private static int AsyncMethod(CancellationToken ct, int n) { Thread.Sleep(1000); PrintMessage("Asynchoronous method."); int sum = 0; try { for (int i = 1; i < n; i++) { //When CancellationTokenSource Object call Cancel Method will cause OperationCanceledException Abnormal, //By calling CancellationToken Of ThrowIfCancellationRequested Method to check whether the operation has been cancelled, //This method and CancellationToken Of IsCancellationRequested Properties are similar. ct.ThrowIfCancellationRequested(); Thread.Sleep(500); //Operation overflow check checked { sum += i; } } } catch (Exception e) { Console.WriteLine("Exception is:" + e.GetType().Name); Console.WriteLine("Operation is canceled."); } return sum; } }
The operation results are as follows:
4.3 task factory
Asynchronous operation can also be realized through TaskFactory type of task factory.
class Program { static void Main(string[] args) { #region Asynchronous with task factory ThreadPool.SetMaxThreads(1000, 1000); Task.Factory.StartNew(() => PrintMessage("Main thread.")); Console.Read(); #endregion } /// <summary> /// Print thread pool information /// </summary> /// <param name="data"></param> private static void PrintMessage(string data) { //Get the number of worker threads available in the thread pool and I/O Number of threads ThreadPool.GetAvailableThreads(out int workThreadNumber, out int ioThreadNumber); Console.WriteLine("{0}\n CurrentThreadId is:{1}\n CurrentThread is background:{2}\n WorkerThreadNumber is:{3}\n IOThreadNumbers is:{4}\n", data, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsBackground.ToString(), workThreadNumber.ToString(), ioThreadNumber.ToString()); } }
The operation results are as follows: