線程池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);
執行緒池使用很簡單,但又有一些限制:
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);
}
}
執行結果:
「假開始」控制操作,本質上並沒有實現讓指定工作在希望的時候開始工作。這裡 在初始化 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# 多執行緒--執行緒池的詳細介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!