首頁 > 軟體

C#多執行緒系列之手動執行緒通知

2022-02-13 19:00:23

區別與範例

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#多執行緒系列之手動執行緒通知的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com