大家可以看到,在上面的常式中,同步是通過等待Monitor.Pulse()來完成的。首先生產者生產了一個值,而同一時刻消費者處於等待狀態,直到收到生產者的“脈衝(Pulse)”通知它生產已經完成,此後消費者進入消費狀態,而生產者開始等待消費者完成操作後將調用Monitor.Pulese()發出的“脈衝”。它的執行結果很簡單:
Produce: 1 Consume: 1 Produce: 2 Consume: 2 Produce: 3 Consume: 3 ... ... Produce: 20 Consume: 20 |
事實上,這個簡單的例子已經協助我們解決了多線程應用程式中可能出現的大問題,只要領悟瞭解決線程間衝突的基本方法,很容易把它應用到比較複雜的程式中去。
四、線程池和定時器——多線程的自動管理
在多線程的程式中,經常會出現兩種情況。一種情況下,應用程式中的線程把大部分的時間花費在等待狀態,等待某個事件發生,然後才能給予響應;而另外一種情況則是線程平常都處於休眠狀態,只是周期性地被喚醒。在.net framework裡邊,我們使用ThreadPool來對付第一種情況,使用Timer來對付第二種情況。
ThreadPool類提供一個由系統維護的線程池——可以看作一個線程的容器,該容器需要Windows 2000以上版本的系統支援,因為其中某些方法調用了只有高版本的Windows才有的API函數。你可以使用ThreadPool.QueueUserWorkItem()方法將線程安放線上程池裡,該方法的原型如下:
//將一個線程放進線程池,該線程的Start()方法將調用WaitCallback代理對象代表的函數
public static bool QueueUserWorkItem(WaitCallback);
//重載的方法如下,參數object將傳遞給WaitCallback所代表的方法
public static bool QueueUserWorkItem(WaitCallback, object);
要注意的是,ThreadPool類也是一個靜態類,你不能也不必要產生它的對象,而且一旦使用該方法線上程池中添加了一個項目,那麼該項目將是沒有辦法取消的。在這裡你無需自己建立線程,只需把你要做的工作寫成函數,然後作為參數傳遞給ThreadPool.QueueUserWorkItem()方法就行了,傳遞的方法就是依靠WaitCallback代理對象,而線程的建立、管理、運行等等工作都是由系統自動完成的,你無須考慮那些複雜的細節問題,線程池的優點也就在這裡體現出來了,就好像你是公司老闆——只需要安排工作,而不必親自動手