這篇文章主要針對System.Threading.AutoResetEvent這個類別的間單使用,自己對執行緒(Thread)也還是幼幼班等級,歡迎看到這篇文章的讀者對於文中有誤或是要補充的不吝賜教。
唯一的建構子則為: public AutoResetEvent(bool initialState) 這邊的輸入參數表明了這個事件一開始的信號狀態(signal state)為:1.已收到信號(signaled) 或2.未收到信號(non-signaled)。 這兩者的差異會在實驗方法中稍微看出初始狀態對Thread行為的一些差異。
研究方法:
Step1. 為求環境單純一點,請先開啟一個Console Project(主控台應用程式)。
引用所需要的命名空間,要引用的就是只有這兩個命名空間:
using System; using System.Threading;
Step2.
class Program { public static Thread t1; // 初始狀態為 non-signalled public static AutoResetEvent ar1 = new AutoResetEvent(false); static void Main(string[] args) { t1 = new Thread(() => { Console.WriteLine("Thread T1 simulating some work for 5 seconds."); // 這裡用睡覺模擬執行一些I/O bound的作業。 Thread.Sleep(5000); Console.WriteLine("Thread T1 finished some work."); // 設定 ar1 狀態為signaled。讓主執行緒不用等可以繼續跑。 ar1.Set(); Console.WriteLine("Thread T1 end."); }); t1.Name = "T1"; t1.Start(); ar1.WaitOne();// waite for signal.除非等到狀態為signaled否則主執行緒就會在這裡繼續等下去。 Console.WriteLine("Main Thread end"); Console.Read(); } }
實驗數據與分析:
當成是一開始執行的時候AutoResetEvent的State就設定為non-signaled,所以主執行緒執行到t1.Start();時產生子執行緒來執行t1的方法(這裡使用lambda statement來偷懶,做一個很間單的事情。)之後,主執行緒往下執行到ar1.WaiteOne();就發現目前State依然是non-signaled,必須等到State設為signaled才能繼續往下執行,因此等到子執行緒中把ar1的State設為Signaled時才會回到主執行緒讓"Main Thread end."最後才列印出來。
ps.你可以試著把ar1的狀態在初始時設為signaled,看看執行起來的結果又是如何?
結論:
當你需要使用多執行緒讓你的I/O Bound作業不影響到整個執行緒的流暢時,可以考慮使用這個簡單的方法讓一些耗費I/O時間的工作移到主執行緒之外,等到需要拿來用之前使用WaiteOne()方法來確保執行完畢後再接續進行後續的工作。
參考文獻:
1.MSDN AutoResetEvent Class
http://msdn.microsoft.com/en-us/library/system.threading.autoresetevent.aspx
2.Code Project Threading系列文章 -- by Sacha Barber => 特別推薦此系列文章此篇文章參考第三章來實作。
特別附註:
若你用Visual Studio中文版來開發,你會發現IDE對Set()還有Reset()這兩個方法的說明很有問題!但若是英文原版的解釋倒是挺清楚的。唔...若英文不是特別爛的話還是會建議各位直接看原文會比較好,若有問題國外的開發者絕對會馬上開炮,官網也會馬上改。(ps.剛剛已經把訂正過後的翻譯送出審查,不知道什麼時候會改。 讓我生氣的是簡體中文的翻譯竟然沒有問題...那繁體是怎麼回事 = =?!)
有圖有真相:
沒有留言:
張貼留言