C # thread pool for multithreading article 2,
In the previous article C # thread pool of multithreading Article 1, we mainly learned how to call the delegate in the thread pool and how to execute asynchronous operations in the thread pool. In this article, we will learn about thread pools, concurrency, and cancellation options.
Iii. Thread Pool and degree of Parallelism
In this section, we will learn about the performance differences between a large number of asynchronous operations, the use of thread pools and the use of separate threads. The procedure is as follows:
1. Use Visual Studio 2015 to create a new console application.
2. Double-click to open the "Program. cs" file and write the code as follows:
1 using System; 2 using System.Diagnostics; 3 using System.Threading; 4 using static System.Console; 5 using static System.Threading.Thread; 6 7 namespace Recipe03 8 { 9 class Program10 {11 static void UseThreads(int numberOfOperations)12 {13 using(var countdown=new CountdownEvent(numberOfOperations))14 {15 WriteLine("Scheduling work by creating threads");16 for(int i = 0; i < numberOfOperations; i++)17 {18 var thread = new Thread(() =>19 {20 Write($"{CurrentThread.ManagedThreadId},");21 Sleep(100);22 countdown.Signal();23 });24 thread.Start();25 }26 countdown.Wait();27 WriteLine();28 }29 }30 31 static void UseThreadPool(int numberOfOperations)32 {33 using(var countdown=new CountdownEvent(numberOfOperations))34 {35 WriteLine("Starting work on a threadpool");36 for(int i = 0; i < numberOfOperations; i++)37 {38 ThreadPool.QueueUserWorkItem(_ =>39 {40 Write($"{CurrentThread.ManagedThreadId},");41 Sleep(100);42 countdown.Signal();43 });44 }45 countdown.Wait();46 WriteLine();47 }48 }49 50 static void Main(string[] args)51 {52 const int numberOfOperations = 500;53 var sw = new Stopwatch();54 sw.Start();55 UseThreads(numberOfOperations);56 sw.Stop();57 WriteLine($"Execution time using threads: {sw.ElapsedMilliseconds}");58 59 sw.Reset();60 sw.Start();61 UseThreadPool(numberOfOperations);62 sw.Stop();63 WriteLine($"Execution time using the thread pool: {sw.ElapsedMilliseconds}");64 }65 }66 }
3. Run the console application. The running effect may be different each time, as shown in:
In the above Code, we first created 500 threads to execute asynchronous operations. We found that the time consumed for executing asynchronous operations using each separate thread was 175 milliseconds. Then we use the thread pool to execute 500 asynchronous operations. We found that the time consumed was 9432 milliseconds. This indicates that using the thread pool to execute highly concurrent asynchronous operations will save the memory and number of threads of the operating system, but will seriously affect the application performance.
Iv. Enable the cancel Option
In this section, we will learn how to cancel an asynchronous operation in the thread pool. The procedure is as follows:
1. Use Visual Studio 2015 to create a new console application.
2. Double-click to open the "Program. cs" file and write the code as follows:
1 using System; 2 using System. threading; 3 using static System. console; 4 using static System. threading. thread; 5 6 namespace Recipe04 7 {8 class Program 9 {10 // CancellationToken. 11 static void AsyncOperation1 (CancellationToken token) 12 {13 WriteLine ("Starting the first task"); 14 for (int I = 0; I <5; I ++) 15 {16 // IsCancellationRequested: Gets whether this flag has been requested to be canceled. 17 // true if you have requested to cancel this flag; otherwise, false. 18 if (token. isCancellationRequested) 19 {20 WriteLine ("The first task has been canceled. "); 21 return; 22} 23 Sleep (TimeSpan. fromSeconds (1); 24} 25 WriteLine ("The first task has completed succesfully"); 26} 27 28 static void AsyncOperation2 (CancellationToken token) 29 {30 try 31 {32 WriteLine ("Starting the second task"); 33 for (int I = 0; I <5; I ++) 34 {35 // if you have requested to cancel this flag, System is triggered. opera TionCanceledException. 36 token. throwIfCancellationRequested (); 37 Sleep (TimeSpan. fromSeconds (1); 38} 39 WriteLine ("The second task has completed succesfully"); 40} 41 catch (OperationCanceledException) 42 {43 WriteLine ("The second task has been canceled. "); 44} 45} 46 47 static void AsyncOperation3 (CancellationToken token) 48 {49 bool cancellationFlag = false; 50 // register one will cancel this System. threading. cancellationToken Call delegate. 51 // The Register parameter is an Action-type delegate, Which is canceled in the System. threading. run 52 token when CancellationToken is used. register () => cancellationFlag = true); 53 WriteLine ("Starting the third task"); 54 for (int I = 0; I <5; I ++) 55 {56 if (cancellationFlag) 57 {58 WriteLine ("The third task has been canceled. "); 59 return; 60} 61 Sleep (TimeSpan. fromSeconds (1); 62} 63 WriteLine ("The third task has completed succesfully "); 64} 65 66 static void Main (string [] args) 67 {68 // CancellationTokenSource: notifies System. Threading. CancellationToken that it should be canceled. 69 using (var cts = new CancellationTokenSource () 70 {71 // obtain the System. Threading. CancellationTokenSource associated with this System. Threading. CancellationToken. 72 CancellationToken token = cts. Token; 73 ThreadPool. QueueUserWorkItem (_ => AsyncOperation1 (token); 74 Sleep (TimeSpan. FromSeconds (2); 75 // convey the cancel request. 76 cts. Cancel (); 77} 78 79 // CancellationTokenSource: notifies System. Threading. CancellationToken that it should be canceled. 80 using (var cts = new CancellationTokenSource () 81 {82 // obtain the System. Threading. CancellationTokenSource associated with this System. Threading. CancellationToken. 83 CancellationToken token = cts. Token; 84 ThreadPool. QueueUserWorkItem (_ => AsyncOperation2 (token); 85 Sleep (TimeSpan. FromSeconds (2); 86 // convey the cancel request. 87 cts. Cancel (); 88} 89 90 // CancellationTokenSource: notifies System. Threading. CancellationToken that it should be canceled. 91 using (var cts = new CancellationTokenSource () 92 {93 // obtain the System. Threading. CancellationTokenSource associated with this System. Threading. CancellationToken. 94 CancellationToken token = cts. Token; 95 ThreadPool. QueueUserWorkItem (_ => AsyncOperation3 (token); 96 Sleep (TimeSpan. FromSeconds (2); 97 // convey the cancel request. 98 cts. Cancel (); 99} 100 101 Sleep (TimeSpan. FromSeconds (2); 102} 103} 104}
3. Run the console application. The running effect is shown in:
In the above Code, we use the CancellationTokenSource and CancellationToken classes. These two classes were introduced in. NET 4.0 and have now become the de facto standard for canceling asynchronous operations.
In the "AsyncOperation1" method, we only check the "CancellationToken. IsCancellationRequested" attribute by polling. If this attribute is true, this means that our operation has been canceled and we must discard this operation.
In the "AsyncOperation2" method, we call the "ThrowIfCancellationRequested" method of CancellationToken to check whether the operation has been canceled. If the operation has been canceled, this method throws an OperationCanceledException exception, we use the try/catch Block to catch this exception to stop the asynchronous operation.
In the "AsyncOperation3" method, we call the "Register" method of CancellationToken to Register a callback method called when an asynchronous operation is canceled. This method allows us to link the logic of the cancel operation to another asynchronous operation.