您好,登錄后才能下訂單哦!
這篇文章主要介紹了C#中多線程的線程池是什么,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
線程池System.Threading.ThreadPool,可用于發送工作項、處理異步I/O、代表其它線程等待以及處理計時器。基本用法:
public void Main() { ThreadPool.QueueUserWorkItem(JobForAThread); // 將某工作交給線程池}void JobForAThread(object state) // 線程要執行的工作:滿足 委托WaitCallback {for (int i = 1; i <= 5; i++) { Console.WriteLine("Running Thread {0},Step {1}", Thread.CurrentThread.ManagedThreadId, i); Thread.Sleep(500); } }
在執行 ThreadPool.QueueUserWorkItem() 方法后,處理器就會自動在池中選擇一個線程來處理“工作內容”。
1.如果線程池還沒有運行,就會創建一個線程池,并啟動第一個線程。
2.如果線程池已經在運行,且至少有一個空閑的線程,線程池就會把改“工作內容”交給這個空閑的線程來處理。
3.如果當時線程池沒有空閑的線程,該工作就會處于等待狀態,直到有空閑線程來處理它。
通過 ThreadPool.GetMaxThreads() 方法來 檢索可以同時處于活動狀態的線程池請求的數目。
int vWorkerThreads; int vCompletionPortThreads; ThreadPool.GetMaxThreads(out vWorkerThreads, out vCompletionPortThreads); Console.WriteLine("池中輔助線程的最大數{0},池中異步 I/O 線程的最大數{1}", vWorkerThreads, vCompletionPortThreads);
可以通過 ThreadPool.SetMaxThreads() 方法設置可以同時處于活動狀態的線程池請求的數目。
ThreadPool.SetMaxThreads(5, 4);
但是,不能將輔助線程的數目或異步I/O完成線程的數目設置位 小于 計算機處理器的數目。線程池使用很簡單,但又一些限制:
1.線程池中的所有線程都是后臺線程。如果進程的所有前臺線程都結束了,所有后臺線程就會停止。不能把入池的線程改為前臺線程。
2.不能給入池的線程設置優先級或名稱。
3.入池的線程只能用于時間較短的任務。如果線程要一直運行,就應該使用Thread類創建一個線程。
給 JobForAThread() 工作任務傳遞參數 object state,調用:
public void Main() { ThreadPool.QueueUserWorkItem(JobForAThread,"這是傳遞給工作內容的參數"); // 添加工作的同時,傳遞參數Console.ReadKey(); // 讓主線程等待,否則“一閃而過” }void JobForAThread(object state) { Console.WriteLine("收到信息:{0}", (string)state); // 處理傳進來的數據for (int i = 1; i <= 5; i++) { Console.WriteLine("Running Thread {0},Step {1}", Thread.CurrentThread.ManagedThreadId, i); Thread.Sleep(500); } }
簡單的控制操作
一般情況下,“工作”交給線程池后,就不受控制了, 它會由處理器自動決定什么時候開始執行(當然是有空閑線程才行)。可以通過以下代碼,讓工作在指定時候以后再開始執行。
ManualResetEvent mManualEvent;public void Main() { mManualEvent = new ManualResetEvent(false); // 實例ThreadPool.QueueUserWorkItem(JobForAThread); Console.WriteLine("{0} 任務已經交給線程池了,但是它沒有執行.", DateTime.Now.ToString("HH:mm:ss")); Thread.Sleep(10000); // 等待 10smManualEvent.Set(); // 發出信號,讓線程繼續執行 Console.ReadKey(); // 讓主線程等待,否則“一閃而過” }void JobForAThread(object state) { mManualEvent.WaitOne(); // 等待 “ mManualEvent.Set();” 這一句執行(發送信號)Console.WriteLine("{0} 現在開始執行任務啦.", DateTime.Now.ToString("HH:mm:ss"));for (int i = 1; i <= 5; i++) { Console.WriteLine("Running Thread {0},Step {1}", Thread.CurrentThread.ManagedThreadId, i); Thread.Sleep(500); } }
運行結果:
這里在將工作交給線程池后,線程執行工作時,一直阻塞在 mManualEvent.WaitOne(); 這一句,直到10s后主線程發出了信號,該工作才繼續執行后續代碼。這是一種“假開始”控制操作,本質上并沒有實現讓指定工作在希望的時候開始工作。這里 在初始化 ManualResetEvent 對象時參數 false 表示,默認將信號置為“阻塞狀態”,通過代碼 mManualEvent.Set(); 將信號置為“可繼續狀態”。反之,可以通過代碼 mManualEvent.Reset(); 將線程置為“阻塞狀態”。
有時,需要等待所有線程池中的線程執行完成后,才繼續執行其它某些代碼。
AutoResetEvent[] mAutoResetEvent;public void Main() { mAutoResetEvent = new AutoResetEvent[]{new AutoResetEvent(false), // 默認信號為 阻塞new AutoResetEvent(false),new AutoResetEvent(false) };for (int i = 0; i < 3; i++) // 創建3個工作 { Thread.Sleep(1000); ThreadPool.QueueUserWorkItem(JobForAThread, i); } Console.WriteLine("所有工作已經添加到池中..."); WaitHandle.WaitAll(mAutoResetEvent); // 等待 mAutoResetEvent 中所有信號變為 繼續 后,繼續后面代碼Console.WriteLine("所有工作已經完成了"); Console.ReadKey(); // 讓主線程等待,否則“一閃而過” }void JobForAThread(object state) {int vJobIndex = (int)state; Console.WriteLine("Job {0} Started.", vJobIndex);for (int i = 1; i <= 5; i++) { Console.WriteLine("Running Thread {0},Step {1},Job {2} ", Thread.CurrentThread.ManagedThreadId, i, vJobIndex); Thread.Sleep(500); } mAutoResetEvent[vJobIndex].Set(); }
運行結果:
感謝你能夠認真閱讀完這篇文章,希望小編分享的“C#中多線程的線程池是什么”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。