當一個線程直到收到另一個線程的通知才執(zhí)行相關(guān)的動作,這時候,就可以考慮使用"事件等待句柄(Event Wait Handles)"。使用"事件等待句柄"主要用到3個類: AutoResetEvent, ManualResetEvent以及CountdownEvent(.NET 4.0以后才有)。本篇包括:
※ 一個線程等待另一個線程的通知※ 2個線程互相通知等待※ 一個線程等待隊列中的多個任務(wù)通知※ 手動控制線程的數(shù)量
□ 一個線程等待另一個線程的通知
最簡單的情景是:發(fā)出信號的線程只發(fā)出一次通知,等待的線程收到通知也只做一次事情。等待的線程肯定有一個等待方法,發(fā)出信號的線程必須有一個發(fā)出信號的方法,AutoResetEvent類提供了相關(guān)方法。
class PRogram{//true表示將初始狀態(tài)設(shè)置為終止狀態(tài)static EventWaitHandle _wait = new AutoResetEvent(false);static void Main(string[] args){new Thread(Waiter).Start();Thread.Sleep(1000);_wait.Set();//發(fā)出指示}static void Waiter(){Console.WriteLine("一切準備就緒,等待指示!");_wait.WaitOne();Console.WriteLine("收到指示~~");}}

○ AutoResetEvent就像地鐵入口的十字轉(zhuǎn)門,有票插入,就讓進,而且每次只讓一個人進。○ 當調(diào)用WaitOne方法,表示該線程已被阻塞,正在等待信號,就像十字轉(zhuǎn)門旁等待進入的乘客。○ 當調(diào)用Set方法,表示發(fā)出信號給等待線程,就像十字轉(zhuǎn)門收到車票,乘客可以通過。
關(guān)于AutoResetEvent:○ 還可通過這種方式創(chuàng)建AutoResetEvent實例:var auto = new EventWaitHandle(false, EventResetMode.AutoReset);○ 如果調(diào)用了Set方法,卻沒有其它線程調(diào)用WaitOne方法,這個handle會一直存在○ 如果調(diào)用Set方法多次,卻有多個線程調(diào)用WaitOne方法,也只能讓這些線程挨個接收信號,即每次只有一個線程接收信號○ WaitOne還有幾個接收時間間隔參數(shù)的重載方法,使用WaitOne(0)可以測試一個wait handle是否已經(jīng)打開○ GC自動回收wait handles
□ 2個線程互相通知等待
還有一種情形:發(fā)出信號的線程要發(fā)出多次通知,每一次需要確認等待線程收到后再發(fā)下一個通知。大概的過程就是:線程A第一次做事并發(fā)出通知,進入等待狀態(tài);線程B收到通知,發(fā)出通知,通知線程A,線程B進入等待狀態(tài);線程A收到線程B的通知,第二次做事并發(fā)出通知,進入等待狀態(tài)......2個線程互相通知,每個線程既是發(fā)出信號者,也是等待者。借助AutoResetEvent類可以解決此需求。
class Program{static EventWaitHandle _ready = new AutoResetEvent(false);static EventWaitHandle _go = new AutoResetEvent(false);static readonly object o = new object();private static string _msg;static void Main(string[] args){new Thread(DoSth).Start();//第一次等待直到另外一個線程準備好_ready.WaitOne();lock (o){_msg = "你好";
新聞熱點
疑難解答