C#多线程---线程池的工作者线程
一、线程池简介
创建和销毁线程是一个要耗费大量时间的过程,太多的线程也会浪费内存资源,所以通过Thread类来创建过多的线程反而有损于性能,为了改善这样的问题 ,.net中就引入了线程池。
线程池形象的表示就是存放应用程序中使用的线程的一个集合。
CLR初始化时,线程池中是没有线程的,在内部, 线程池维护了一个操作请求队列,当应用程序想执行一个异步操作时,就调用一个方法,就将一个任务放到线程池的队列中,线程池中代码从队列中提取任务,将这个任务委派给一个线程池线程去执行,当线程池线程完成任务时,线程不会被销毁,而是返回到线程池中,等待响应另一个请求。由于线程不被销毁, 这样就可以避免因为创建线程所产生的性能损失。
注意:通过线程池创建的线程默认为后台线程,优先级默认为Normal.
二、创建方法
public static bool QueueUserWorkItem (WaitCallback callBack);
public static bool QueueUserWorkItem(WaitCallback callback, Object state);
这两个方法向线程池的队列添加一个工作项(work item)以及一个可选的状态数据。
工作项其实就是由callback参数标识的一个方法,该方法将由线程池线程执行。
回调方法必须匹配System.Threading.WaitCallback委托类型,定义为:
public delegate void WaitCallback(Object state);
三、使用例子
(1)正常使用
1 using System; 2 using System.Threading; 3 4 namespace ThreadPoolWorkerItem 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 Console.WriteLine("Thread pool thread test..."); 11 Console.WriteLine(); 12 string myInfo = "The following is the thread info ontained in function Main"; 13 PrintThreadInfo(myInfo); 14 Console.WriteLine(); 15 ThreadPool.QueueUserWorkItem(AsyncMethod); 16 Console.ReadLine(); 17 18 } 19 private static void PrintThreadInfo(string info) 20 { 21 Console.WriteLine(info); 22 Console.WriteLine($"ThreadId:{Thread.CurrentThread.ManagedThreadId}\nIsBackgroundThread:{Thread.CurrentThread.IsBackground}\nIsThreadPoolThread:{Thread.CurrentThread.IsThreadPoolThread}"); 23 int workerThread = 0; 24 int ioThread = 0; 25 ThreadPool.GetMaxThreads(out workerThread, out ioThread); 26 Console.WriteLine($"MaxWorkerThread:{workerThread}\nMaxIoThread:{ioThread}"); 27 int workerThreadAvailable = 0; 28 int ioThreadAvailable = 0; 29 ThreadPool.GetAvailableThreads(out workerThreadAvailable, out ioThreadAvailable); 30 Console.WriteLine($"AvailableWorkerThread:{workerThreadAvailable}\nAvailableIoThread:{ioThreadAvailable}"); 31 } 32 private static void AsyncMethod(object state) 33 { 34 string myInfo = "The following is the thread info ontained in function AsyncMethod"; 35 PrintThreadInfo(myInfo); 36 Thread.Sleep(3000); 37 Console.WriteLine("AsyncMethod done!"); 38 } 39 } 40 }
运行结果如下:
(2)任务取消
下面使用System.Threading.CancellationTokenSource对象来对任务进行取消操作。
1 using System; 2 using System.Threading; 3 4 namespace ThreadPoolWorkerItem 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 Console.WriteLine("Thread pool thread test..."); 11 Console.WriteLine(); 12 //string myInfo = "The following is the thread info ontained in function Main"; 13 //PrintThreadInfo(myInfo); 14 //Console.WriteLine(); 15 16 CancellationTokenSource cts = new CancellationTokenSource(); 17 ThreadPool.QueueUserWorkItem(AsyncMethod, cts.Token); 18 19 while(true) 20 { 21 string myLine = Console.ReadLine(); 22 if(myLine == "quit") 23 { 24 break; 25 } 26 switch(myLine) 27 { 28 case "cancel": 29 Console.WriteLine("Cancel request from user..."); 30 cts.Cancel(); 31 break; 32 } 33 } 34 35 } 36 private static void PrintThreadInfo(string info) 37 { 38 Console.WriteLine(info); 39 Console.WriteLine($"ThreadId:{Thread.CurrentThread.ManagedThreadId}\nIsBackgroundThread:{Thread.CurrentThread.IsBackground}\nIsThreadPoolThread:{Thread.CurrentThread.IsThreadPoolThread}"); 40 int workerThread = 0; 41 int ioThread = 0; 42 ThreadPool.GetMaxThreads(out workerThread, out ioThread); 43 Console.WriteLine($"MaxWorkerThread:{workerThread}\nMaxIoThread:{ioThread}"); 44 int workerThreadAvailable = 0; 45 int ioThreadAvailable = 0; 46 ThreadPool.GetAvailableThreads(out workerThreadAvailable, out ioThreadAvailable); 47 Console.WriteLine($"AvailableWorkerThread:{workerThreadAvailable}\nAvailableIoThread:{ioThreadAvailable}"); 48 } 49 private static void AsyncMethod(object state) 50 { 51 //string myInfo = "The following is the thread info ontained in function AsyncMethod"; 52 //PrintThreadInfo(myInfo); 53 CancellationToken cltToken = (CancellationToken)state; 54 int myCountNumber = 100; 55 for (int i = 0; i < myCountNumber; i++) 56 { 57 Console.WriteLine(i); 58 if (cltToken.IsCancellationRequested) 59 { 60 Console.ForegroundColor = ConsoleColor.DarkRed; 61 Console.WriteLine($"Counting is cancelled. Current:{i} / Total:{myCountNumber}"); 62 Console.ResetColor(); 63 return; 64 } 65 Thread.Sleep(3000); 66 67 } 68 Console.WriteLine("Counting is done!"); 69 } 70 } 71 }
运行结果如下: