多執行緒系列(三)之執行緒池
阿新 • • 發佈:2020-08-24
什麼是執行緒池?
.NetFramework1.0時代的Thread,API功能繁多,對執行緒的數量是沒有管控的,在.NetFramework2.0時代推出了ThreadPool,如果某個物件建立和銷燬代價比較高,同時這個物件還可以反覆使這些執行緒,就需要使用執行緒池,執行緒池可以儲存多個執行緒物件,需要使用執行緒時直接從執行緒池裡面拿,使用完之後不做釋放,又放回池子(享元模式),需要用的時候再去拿。這樣可以減少建立執行緒的開銷,提升效能,此外,還可以管控執行緒的總數量,防止資源濫用。
委託非同步呼叫、Task、Parrallel、async/await的執行緒全部都是執行緒池裡面的執行緒。直接new Thread開起的執行緒不受執行緒池的數量限制(但是會佔用執行緒池的執行緒數量)。
使用執行緒池開啟執行緒
ThreadPool.QueueUserWorkItem(o=>this.DoSomeThing("btnThreadPool_Click_1")); ThreadPool.QueueUserWorkItem(o => { this.DoSomeThing("btnThreadPool_Click_2"); Console.WriteLine( o?.ToString()); }, "wjl");
檢索和設定執行緒池的最大最小數目和非同步IO執行緒的最大最小數目
I/O執行緒是.NET專為訪問外部資源所設定的一種執行緒,因為訪問外部資源常常要受到外界因素的影響,為了防止讓主執行緒受影響而長期處於阻塞狀態,.NET為多個I/O操作都建立起了非同步方法。
//檢索由 GetMaxThreads 返回的執行緒池執行緒的最大數目和非同步IO執行緒的最大數目 ThreadPool.GetMaxThreads(out int workerThreads, out int completionPortThreads); Console.WriteLine($"當前執行緒池最大數目為:{workerThreads},最大非同步IO執行緒:{completionPortThreads}"); //檢索由 GetMinThreads 返回的執行緒池執行緒的最小數目和非同步IO執行緒的最小數目 ThreadPool.GetMinThreads(out int workerThreadsMin, out int completionPortThreadsMin); Console.WriteLine($"當前執行緒池最小數目為:{workerThreadsMin},最小非同步IO執行緒:{completionPortThreadsMin}"); ThreadPool.SetMaxThreads(8, 8);//設定的最大值,必須大於CPU核數,否則設定無效 ThreadPool.SetMinThreads(2, 2);
執行緒等待
單個執行緒等待:
//執行緒等待 ManualResetEvent mre = new ManualResetEvent(false); //ManualResetEvent是一種訊號量的方式 //如果初始為false--關閉, mre.Set()之後變為ture,WaitOne就能通過 //如果初始為tue--開啟, mre.Rset()之後變為false,WaitOne就只能等待 ThreadPool.QueueUserWorkItem(o => { this.DoSomeThing("btnThreadPool_Click_3"); mre.Set(); }); mre.WaitOne(); Console.WriteLine("任務已經完成了...");
多個執行緒等待:
ManualResetEvent[] mres = new ManualResetEvent[10]; for (int i = 0; i < 10; i++) { mres[i] = new ManualResetEvent(false); int k = i; ThreadPool.QueueUserWorkItem(o => { this.DoSomeThing($"mres{k}"); ManualResetEvent mre = o as ManualResetEvent; mre.Set(); }, mres[i]); } //等待所有陣列中的元素都收到訊號,如果是控制檯程式或者winform程式,請將Main()函式上面的特性[STAThread]註釋掉 WaitHandle.WaitAll(mres); Console.WriteLine("多個任務已經完成了...");