筆者的一台激光測厚設備的軟件, 它有一個運動線程, 一個激光數據處理線程.
運動線程做的事就是由A點移動到B點, 然後再由B點移動回A點.
激光處理線程要做的事就是采集指定數量點的激光數據, 隨著采集的點數增加, 耗時也會增加.
這兩個線程就存在線程同步的問題, 預想的標准流程應該是這樣的:
這樣的線程同步要求, 可以使用C#的一個封裝windows內核信號量的類ManualResetEvent來實現, 它是筆者用得最多的一個類. 所以在這裡重點記錄下來.
ManualResetEvent的功能我們先做一個簡要說明:
ManualResetEvent可以通知一個或多個正在等待的線程已發生事件,允許線程通過發信號互相通信,來控制線程是否可心訪問資源
當一個線程開始一個活動(此活動必須完成後,其他線程才能開始)時,它調用 Reset 以將 ManualResetEvent 置於非終止狀態。此線程可被視為控制 ManualResetEvent。調用 ManualResetEvent 上的 WaitOne 的線程將阻止,並等待信號。當控制線程完成活動時,它調用 Set 以發出等待線程可以繼續進行的信號。並釋放所有等待線程。
一旦它被終止,ManualResetEvent 將保持終止狀態,直到它被手動重置。即對 WaitOne 的調用將立即返回。
可以通過將布爾值傳遞給構造函數來控制 ManualResetEvent 的初始狀態,如果初始狀態處於終止狀態,為 true;否則為 false。
看理論要結合代碼驗證, 這樣更容易明白.
下面給出演示代碼:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 7 namespace ManualResetEventState 8 { 9 class Program 10 { 11 static ManualResetEvent _mre = new ManualResetEvent(false); 12 static void Main(string[] args) 13 { 14 Console.WriteLine("輸入1為Set() 開始運行"); 15 Console.WriteLine("輸入2為Reset() 暫停運行"); 16 Thread[] _threads = new Thread[3]; 17 18 for (int i = 0; i < _threads.Count(); i++) 19 { 20 _threads[i] = new Thread(ThreadRun); 21 _threads[i].Start(); 22 } 23 24 while (true) 25 { 26 switch (Console.ReadLine()) 27 { 28 case "1": 29 _mre.Set(); 30 Console.WriteLine("開始運行"); 31 break; 32 case "2": 33 _mre.Reset(); 34 Console.WriteLine("暫停運行"); 35 break; 36 default: 37 break; 38 } 39 } 40 } 41 42 static void ThreadRun() 43 { 44 int _threadID = 0; 45 while (true) 46 { 47 _mre.WaitOne(); 48 _threadID = Thread.CurrentThread.ManagedThreadId; 49 Console.WriteLine("current Tread is " + _threadID); 50 Thread.Sleep(TimeSpan.FromSeconds(2)); 51 52 } 53 } 54 } 55 }
運行結果如下圖:
本文源代碼下載