C#多線程之ManualResetEvent和AutoResetEvent

初次體驗

ManualResetEvent和AutoResetEvent主要負責多線程編程中的線程同步;以下一段是引述網上和MSDN的解析:

在.Net多線程編程中,AutoResetEvent和ManualResetEvent這兩個類經常用到, 他們的用法很類似,但也有區別。Set方法將信號置爲發送狀態,Reset方法將信號置爲不發送狀態,WaitOne等待信號的發送。可以通過構造函數的參數值來決定其初始狀態,若爲true則非阻塞狀態,爲false爲阻塞狀態。如果某個線程調用WaitOne方法,則當信號處於發送狀態時,該線程會得到信號, 繼續向下執行。其區別就在調用後,AutoResetEvent.WaitOne()每次只允許一個線程進入,當某個線程得到信號後,AutoResetEvent會自動又將信號置爲不發送狀態,則其他調用WaitOne的線程只有繼續等待.也就是說,AutoResetEvent一次只喚醒一個線程;而ManualResetEvent則可以喚醒多個線程,因爲當某個線程調用了ManualResetEvent.Set()方法後,其他調用WaitOne的線程獲得信號得以繼續執行,而ManualResetEvent不會自動將信號置爲不發送。也就是說,除非手工調用了ManualResetEvent.Reset()方法,則ManualResetEvent將一直保持有信號狀態,ManualResetEvent也就可以同時喚醒多個線程繼續執行。

本質上AutoResetEvent.Set()方法相當於ManualResetEvent.Set()+ManualResetEvent.Reset();

因此AutoResetEvent一次只能喚醒一個線程,其他線程還是堵塞

生動示例

用一個三國演義的典故來寫段示例代碼:

話說曹操率領80W大軍準備圍剿劉備和孫權,面對敵衆我寡的情況,諸葛亮與周瑜想到了一個妙計,用裝滿火藥桶的大船去衝擊曹操連在一起的戰船,計劃都安排好了,可謂“萬事俱備 只欠東風”。

 
01 using System;
02 using System.Collections.Generic;
03 using System.Linq;
04 using System.Text;
05 using System.Threading;
06   
07 namespace Test
08 {
09     class Program
10     {
11         //默認信號爲不發送狀態
12         private static ManualResetEvent mre = new ManualResetEvent(false); 
13   
14         static void Main(string[] args)
15         {
16             EastWind wind = new EastWind(mre);
17             //啓動東風的線程
18             Thread thd = new Thread(new ThreadStart(wind.WindComming));
19             thd.Start();
20   
21             mre.WaitOne();//萬事俱備只欠東風,事情卡在這裏了,在東風來之前,諸葛亮沒有進攻
22   
23             //東風到了,可以進攻了
24             Console.WriteLine("諸葛亮大吼:東風來了,可以進攻了,滿載燃料的大船接着東風衝向曹操的戰船");
25             Console.ReadLine(); 
26         }
27     }
28   
29     /// <summary>
30     /// 傳說中的東風
31     /// </summary>
32     class EastWind
33     {
34         ManualResetEvent _mre;
35   
36         /// <summary>
37         /// 構造函數
38         /// </summary>
39         /// <param name="mre"></param>
40         public EastWind(ManualResetEvent mre)
41         {
42             _mre = mre;
43         }
44   
45         /// <summary>
46         /// 風正在吹過來
47         /// </summary>
48         public void WindComming()
49         {
50             Console.WriteLine("東風正在吹過來");
51             for (int i = 0; i <= 5; i++)
52             {
53                 Thread.Sleep(500);
54                 Console.WriteLine("東風吹啊吹,越來越近了...");
55             }
56             Console.WriteLine("東風終於到了");
57   
58             //通知諸葛亮東風已到,可以進攻了,通知阻塞的線程可以繼續執行了
59             _mre.Set();
60         }
61     }
62   
63 }

運行結果:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章