先引入一下線程池的概念:
百度百科:線程池是一種多線程處理形式,處理過程中將任務添加到隊列,然后在創建線程后自動啟動這些任務。線程池線程都是后台線程。每個線程都使用默認的堆棧大小,以默認的優先級運行,並處於多線程單元中。如果某個線程在托管代碼中空閑(如正在等待某個事件),則線程池將插入另一個輔助線程來使所有處理器保持繁忙。如果所有線程池線程都始終保持繁忙,但隊列中包含掛起的工作,則線程池將在一段時間后創建另一個輔助線程但線程的數目永遠不會超過最大值。超過最大值的線程可以排隊,但他們要等到其他線程完成后才啟動。
線程池主要方法:
1 // 參數: 2 // workerThreads: 3 // 要由線程池根據需要創建的新的最小工作程序線程數。 4 // completionPortThreads: 5 // 要由線程池根據需要創建的新的最小空閑異步 I/O 線程數。 // 返回結果:如果更改成功,則為 true;否則為 false。
6 [SecuritySafeCritical] 7 public static bool SetMinThreads(int workerThreads, int completionPortThreads); 8 // 參數: 9 // workerThreads: 10 // 線程池中輔助線程的最大數目。 11 // completionPortThreads: 12 // 線程池中異步 I/O 線程的最大數目。 13 // 返回結果:如果更改成功,則為 true;否則為 false。
14 [SecuritySafeCritical] 15 public static bool SetMaxThreads(int workerThreads, int completionPortThreads);
先來看一個簡單的例子:
1 public class Program 2 { 3 const int cycleNum = 10; 4 static void Main(string[] args) 5 { 6 ThreadPool.SetMinThreads(1,1); 7 ThreadPool.SetMaxThreads(5, 5); 8 for(int i = 1; i <= cycleNum; i++) 9 { 10 ThreadPool.QueueUserWorkItem(new WaitCallback(testFun),i.ToString()); 11 } 12 Console.WriteLine("主線程執行!"); 13 Console.WriteLine("主線程結束!"); 14 Console.ReadKey(); 15 } 16 public static void testFun(object obj) 17 { 18 Console.WriteLine(string.Format("{0}:第{1}個線程",DateTime.Now.ToString(),obj.ToString())); 19 Thread.Sleep(5000); 20 } 21 }
附上結果:
這里可以看出,線程池里線程的執行不影響主線程的運行,線程池雖然可以管理多線程的執行,但是卻無法知道它什么時候終止。這時候我們可以利用之前講的信號燈AutoResetEvent和ManualResetEvent來解決問題,對此還不了解的朋友可以參見多線程之AutoResetEvent。
上面代碼稍加改動,如下:
1 public class Program 2 { 3 const int cycleNum = 10; static int cnt = 10; 4 static AutoResetEvent myEvent = new AutoResetEvent(false); 5 static void Main(string[] args) 6 { 7 ThreadPool.SetMinThreads(1,1); 8 ThreadPool.SetMaxThreads(5, 5); 9 for(int i = 1; i <= cycleNum; i++) 10 { 11 ThreadPool.QueueUserWorkItem(new WaitCallback(testFun),i.ToString()); 12 } 13 Console.WriteLine("主線程執行!"); 14 Console.WriteLine("主線程結束!"); 15 myEvent.WaitOne(); 16 Console.WriteLine("線程池終止!"); 17 Console.ReadKey(); 18 } 19 public static void testFun(object obj) 20 { cnt -= 1; 21 Console.WriteLine(string.Format("{0}:第{1}個線程",DateTime.Now.ToString(),obj.ToString())); 22 Thread.Sleep(5000); 23 if (cnt == 0) 24 { 25 myEvent.Set(); 26 } 27 } 28 }
這里,當線程池中所有線程執行完成后,可以捕獲到該事件,我們就可以利用此方法來獲取線程池終止事件了,執行結果如下: