你好,我是阿輝,
前面2篇文章介紹了執行緒的基礎知識和執行緒同步,下面我們來一起認識學習下,執行緒池的使用,
執行緒池
創建執行緒是昂貴的操作,所以為每個短暫的異步操作創建執行緒會產生顯著的開銷,一般情況下,都會使用池,也就是執行緒池進行管理,
執行緒池可以成功地適應于任何需要大量短暫的開銷大的資源,事先分配一定的資源,將這些資源放入到資源池中,每次需要新的資源,只需從池中獲取一個,不需要創建新的,當該資源不再被使用時,就將其回傳到池中,
在.NET中,執行緒池可以使用ThreadPool型別,受.NET通用語言運行時(CLR)管理,每個CLR都有一個執行緒池實體,ThreadPool型別擁有一個QueueUserWorkItem靜態方法,該方法接收一個委托,代表用戶自定義的一個異步操作,該方法被呼叫后,委托會進入到內部佇列中,如果執行緒池中沒有任何執行緒,將創建一個新的作業執行緒并將佇列中第一個委托放入到該作業執行緒中,
保持在執行緒中的操作都是短暫的是非常重要的,不要在執行緒池中放入長時間運行的操作,或者阻塞作業執行緒, 這將導致所有作業執行緒變的繁忙,從而無法服務用戶操作,這會導致性能問題和非常難以調式的錯誤,
在執行緒池中,如果停止向其放置新操作時,執行緒池最侄訓洗掉一定時間后過期的不再使用的執行緒,這將釋放所有那些不再的系統資源,
執行緒池的用途是執行運行時間短的操作,使用執行緒池可以減少并行度耗費及節省作業系統資源,
執行緒池中的作業執行緒都是后臺執行緒,這意味著當所有的前臺執行緒(包括主執行緒)完成后,所有的后臺執行緒將停止作業,
執行緒池中異步的使用
class Program
{
private delegate string RunOnThreadPool(out int threadId); //宣告委托
private static void Callback(IAsyncResult ar)
{
Console.WriteLine("觸發回呼");
Console.WriteLine("異步狀態:" + ar.AsyncState);
Console.WriteLine("是否是執行緒池的執行緒:" + Thread.CurrentThread.IsThreadPoolThread);
Console.WriteLine("ThreadId:" + Thread.CurrentThread.ManagedThreadId);
}
private static string Test(out int threadId)
{
Console.WriteLine("Test開始");
Console.WriteLine("是否是執行緒池的執行緒:" + Thread.CurrentThread.IsThreadPoolThread);
Thread.Sleep(TimeSpan.FromSeconds(2));
threadId = Thread.CurrentThread.ManagedThreadId;
return "ThreadId:" + threadId;
}
static void Main(string[] args)
{
int threadId=0;
RunOnThreadPool poolDelegate=Test;
var t=new Thread(()=>Test(out threadId));
t.Start();
t.Join();
Console.WriteLine("Thread ID="+threadId);
IAsyncResult ar=poolDelegate.BeginInvoke(out threadId,Callback,"測驗是否可以回呼");
ar.AsyncWaitHandle.WaitOne();
string result=poolDelegate.EndInvoke(out threadId,ar);
Console.WriteLine("ID:"+threadId);
Console.WriteLine("結果:"+result);
Console.ReadKey();
}
}
執行后可以看到實際的顯示結果,

由于執行緒的建構式只能接受一個無任何回傳結果的方法,所以這里使用了lambda運算式來將對Test方法的呼叫包起來,
上面是一個很標準的在執行緒池中使用委托的例子,也可以學習到具體執行緒池的應用,可以看到當第一次執行緒池中沒有執行緒時,列印出來執行緒10不在執行緒中,當第二次在執行緒池中時,后面異步回呼顯示出來的結果就是再次呼叫的執行緒11,
BeginInvoke方法接受一個回呼函式,該回呼函式會在異步操作完成后會被呼叫,并且一個用戶自定義的狀態會傳給該回呼函式,該狀態通常用于區分異步呼叫,是一個實作了IAsyncResult介面的result物件,BeginInvoke立即回傳結果,當執行緒池中的作業執行緒在執行異步操作時,仍允許繼續其他作業,可以通過result物件的IsCompleted屬性輪詢結果,當操作完成后,會得到一個結果,可以通過委托呼叫EndInvoke方法,將IAsyncResult物件傳遞給委托引數,
上面這句話其實主要是講解委托在執行緒池中的應用,如果你想得到某個執行緒的回傳結果,就得使用這種異步委托來實作,
在執行緒池中使用委托時,呼叫EndInvoke方法是非常重要的,該方法會將任何未處理的例外拋回到呼叫執行緒中,當使用這種異步API時,請確保始終呼叫Begin和End方法,
上面使用的Begin/End方法和.NET中的IAsyncResult物件等方式被稱為異步編程模型(APM模式),這樣的方法叫異步方法,
執行緒池中還有一個有用的方法:ThreadPool.RegisterWaitForSingleObject,該方法允許我們將回呼函式放入執行緒池中的佇列中,當提供的等待事件處理器收到信號或發生超時時,該回呼函式將被呼叫,
在執行緒池中使用BackgroundWorker組件,可以顯示地指出后臺作業執行緒支持取消操作及操作進度的通知,此時可以使用事件語法,
事件表示了一些通知的源或當通知到達時會有所回應的一系列訂閱者,
這種就是基于事件的異步模式(EAP),就是啟動一個異步操作然后訂閱給不同的事件,這些事件在該操作執行時會被觸發,
小寄語
人生短暫,我不想去追求自己看不見的,我只想抓住我能看的見的,
原創不易,給個關注,
我是阿輝,感謝您的閱讀,如果對你有幫助,麻煩點贊、轉發 謝謝,
作者:阿輝 關注我:微信掃描下面二維碼,6T編程資料免費送, 微信公眾號:Andy阿輝
寫一些程式員的所思所想,希望對你有幫助,
出處:http://www.cnblogs.com/netxiaoahui/ 著作權宣告:本文著作權歸作者和博客園共有,歡迎轉載,
但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利.
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/297949.html
標籤:.NET技术
上一篇:ASP.NET管道處理模型(二)
