C# 多執行緒學習(4) :多執行緒的自動管理(執行緒池)

發表於2015-10-09

在多執行緒的程式中,經常會出現兩種情況:

一種情況: 應用程式中,執行緒把大部分的時間花費在等待狀態,等待某個事件發生,然後才能給予響應。這一般使用ThreadPool(執行緒池)來解決;

另一種情況:執行緒平時都處於休眠狀態,只是週期性地被喚醒。這一般使用Timer(定時器)來解決;

ThreadPool類提供一個由系統維護的執行緒池(可以看作一個執行緒的容器),該容器需要 Windows 2000 以上系統支援,因為其中某些方法呼叫了只有高版本的Windows才有的API函式。

將執行緒安放線上程池裡,需使用ThreadPool.QueueUserWorkItem()方法,該方法的原型如下:

注意

ThreadPool類是一個靜態類,你不能也不必要生成它的物件。而且一旦使用該方法線上程池中新增了一個專案,那麼該專案將是無法取消的。

在這裡你無需自己建立執行緒,只需把你要做的工作寫成函式,然後作為引數傳遞給ThreadPool.QueueUserWorkItem()方法就行了,傳遞的方法就是依靠WaitCallback代理物件,而執行緒的建立、管理、執行等工作都是由系統自動完成的,你無須考慮那些複雜的細節問題。

ThreadPool 的用法:

首先程式建立了一個ManualResetEvent物件,該物件就像一個訊號燈,可以利用它的訊號來通知其它執行緒。

本例中,當執行緒池中所有執行緒工作都完成以後,ManualResetEvent物件將被設定為有訊號,從而通知主執行緒繼續執行。

ManualResetEvent物件有幾個重要的方法:

初始化該物件時,使用者可以指定其預設的狀態(有訊號/無訊號);

在初始化以後,該物件將保持原來的狀態不變,直到它的Reset()或者Set()方法被呼叫:

Reset()方法:將其設定為無訊號狀態;

Set()方法:將其設定為有訊號狀態。

WaitOne()方法:使當前執行緒掛起,直到ManualResetEvent物件處於有訊號狀態,此時該執行緒將被啟用。然後,程式將向執行緒池中新增工作項,這些以函式形式提供的工作項被系統用來初始化自動建立的執行緒。當所有的執行緒都執行完了以後,ManualResetEvent.Set()方法被呼叫,因為呼叫了ManualResetEvent.WaitOne()方法而處在等待狀態的主執行緒將接收到這個訊號,於是它接著往下執行,完成後邊的工作。

ThreadPool 的用法示例:

程式中應該引起注意的地方:

SomeState類是一個儲存資訊的資料結構,它在程式中作為引數被傳遞給每一個執行緒,因為你需要把一些有用的資訊封裝起來提供給執行緒,而這種方式是非常有效的。

程式出現的InterLocked類也是專為多執行緒程式而存在的,它提供了一些有用的原子操作。

原子操作:就是在多執行緒程式中,如果這個執行緒呼叫這個操作修改一個變數,那麼其他執行緒就不能修改這個變數了,這跟lock關鍵字在本質上是一樣的。

我們應該徹底地分析上面的程式,把握住執行緒池的本質,理解它存在的意義是什麼,這樣才能得心應手地使用它。

相關文章