筆者的一台激光測厚設備的軟件, 它有一個運動線程, 一個激光數據處理線程.
運動線程做的事就是由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 }
運行結果如下圖:

本文源代碼下載