C#多線程系列之手動線程通知

區別與示例

AutoResetEvent 和 ManualResetEvent 十分相似。兩者之間的區別,在於前者是自動(Auto),後者是手動(Manua)。

你可以先運行下面的示例,再測試兩者的區別。

AutoResetEvent 示例:

    class Program
    {
        // 線程通知
        private static AutoResetEvent resetEvent = new AutoResetEvent(false);

        static void Main(string[] args)
        {
            // 創建線程
            new Thread(DoOne).Start();

            // 用於不斷向另一個線程發送信號
            while (true)
            {
                Console.ReadKey();
                resetEvent.Set();           // 發生通知,設置終止狀態
            }
        }

        public static void DoOne()
        {
            Console.WriteLine("① 等待中,請發出信號允許我運行");
            resetEvent.WaitOne();

            Console.WriteLine("② 等待中,請發出信號允許我運行");

            resetEvent.WaitOne();
            Console.WriteLine("③ 等待中,請發出信號允許我運行");
            
            // ...

            Console.WriteLine("線程結束");
        }
    }

ManualResetEvent 類示例:

    class Program
    {
        private static ManualResetEvent resetEvent = new ManualResetEvent(false);
        static void Main(string[] args)
        {
            new Thread(DoOne).Start();
            // 用於不斷向另一個線程發送信號
            while (true)
            {
                Console.ReadKey();
                resetEvent.Set();           // 發生通知,設置終止狀態
            }
        }

        public static void DoOne()
        {
            Console.WriteLine("等待中,請發出信號允許我運行");
            resetEvent.WaitOne();

            // 後面的都無效,線程會直接跳過而無需等待
            resetEvent.WaitOne();
            resetEvent.WaitOne();
            resetEvent.WaitOne();
            resetEvent.WaitOne();
            resetEvent.WaitOne();
            Console.WriteLine("線程結束");
        }
    }

因為 AutoResetEvent 對象在 .WaitOne() 方法等待信號完畢後,會自動重置為非終止狀態,相當於高速收費站自動閘門,一輛車過去後,機器自動關閘。

ManualResetEvent 相當於人工閘門,打開後編寫人工關閉閘門,不然的話閘門會一直處於打開狀態。

ManualResetEvent 主要用於更加靈活的線程信號傳遞場景。

ManualResetEvent 類

表示線程同步事件,收到信號時,要想下一次依然生效,必須手動重置該事件。

因為 ManualResetEvent 類跟 AutoManualResetEvent 類十分接近,這裡就不贅述瞭。

它們的使用區別主要是:

AutoResetEvent 類,每次 Set() ,跳過一個 WaitOne()。因為會 自動恢復設置,所以下次碰到 WaitOne() 會繼續等待。

ManualResetEvent 類, Set() 後,不會重置設置,因此一旦使用瞭 Set() 後,就會一路放通,不會再等待。

其構造函數如下:

構造函數 說明
ManualResetEvent(Boolean) 用一個指示是否將初始狀態設置為終止的佈爾值初始化 ManualResetEvent 類的新實例。

其常用方法如下:

方法 說明
Close() 釋放由當前 WaitHandle 占用的所有資源。
Reset() 將事件狀態設置為非終止,從而導致線程受阻。
Set() 將事件狀態設置為有信號,從而允許一個或多個等待線程繼續執行。
WaitOne() 阻止當前線程,直到當前 WaitHandle 收到信號。
WaitOne(Int32) 阻止當前線程,直到當前 WaitHandle 收到信號,同時使用 32 位帶符號整數指定時間間隔(以毫秒為單位)。
WaitOne(Int32, Boolean) 阻止當前線程,直到當前的 WaitHandle 收到信號為止,同時使用 32 位帶符號整數指定時間間隔,並指定是否在等待之前退出同步域。
WaitOne(TimeSpan) 阻止當前線程,直到當前實例收到信號,同時使用 TimeSpan 指定時間間隔。
WaitOne(TimeSpan, Boolean) 阻止當前線程,直到當前實例收到信號為止,同時使用 TimeSpan 指定時間間隔,並指定是否在等待之前退出同步域。

ManualResetEventSlim

ManualResetEventSlim 相對 ManualResetEvent ,當等待時間預計非常短並且事件不跨越進程邊界時,可以使用此類來獲得比 ManualResetEvent 更好的性能。

從代碼使用來看,沒有啥區別,主要就是考慮性能下時,兩者不同場景。

這裡就不對這兩個類型贅述瞭。

到此這篇關於C#多線程系列之手動線程通知的文章就介紹到這瞭。希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。

推薦閱讀: