C# 總結ManualResetEvent與AutoResetEvent【一】

C# 總結ManualResetEvent與AutoResetEvent【一】

 ManualResetEvent:

ManualResetEvent 允許線程通過發信號互相通信。通常,此通信涉及一個線程在其他線程進行之前必須完成的任務。當一個線程開始一個活動(此活動必須完成後,其他線程才能開始)時,它調用 Reset 以將 ManualResetEvent 置於非終止狀態,此線程可被視爲控制 ManualResetEvent。調用 ManualResetEvent 上的 WaitOne 的線程將阻止,並等待信號。當控制線程完成活動時,它調用 Set 以發出等待線程可以繼續進行的信號。並釋放所有等待線程。一旦它被終止,ManualResetEvent 將保持終止狀態(即對 WaitOne 的調用的線程將立即返回,並不阻塞),直到它被手動重置。可以通過將布爾值傳遞給構造函數來控制 ManualResetEvent 的初始狀態,如果初始狀態處於終止狀態,爲 true;否則爲 false。

案例分析:

1.比如我們現在有兩個線程操作以及List<string>集合,一個線程往集合裏面加數據,一個線程刪數據。現在有這麼一個條件,前提是集合裏面數據大於5條的時候,才通知刪除的線程,來刪除集合裏面的數據,如果集合裏面數據不大於5條,就不執行刪除,一直阻塞刪除的線程,等待數據大於5條;

 定義List<string>集合與ManualResetEvent對象

static List<string> list = new List<string>();
private static ManualResetEvent met = new ManualResetEvent(false);

代碼如下:往集合中加數據

       
        /// <summary>
        /// 往list里加數據
        /// </summary>
        /// <returns></returns>
        public static List<string> AddtoList()
        {
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    for (int i = 0; i <= 11; i++)
                    {
                        list.Add("list項目" + i);
                        Console.WriteLine("添加到第" + i);
                        Thread.Sleep(2000); 
                    }
                }
            });
            return list;
        }

 從集合中刪除數據:

 public static void DeteleFromList(List<string> list)
        {
            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    met.WaitOne();//阻塞當前線程
                    if (list.Count > 0)
                    {
                        for (int i = 0; i < list.Count; i++)
                        {
                            list.RemoveAt(0);
                            Console.WriteLine("刪除了" + i);
                        }
                    }
                }
            });
        }

Main函數中,調用:

 static void Main(string[] args)
        {
            List<string> s = new List<string>();
            s = AddtoList();
            while (true)
            {
                if (s.Count >= 5)
                {
                    met.Set();
                    DeteleFromList(s);
                }
                if (s.Count == 0)
                {
                    met.Reset();
                }
            }
        }

執行效果: 

 

AutoResetEvent 

AutoResetEvent(bool initialState):構造函數,用一個指示是否將初始狀態設置爲終止的布爾值初始化該類的新實例。

      False:無信號,子線程的WaitOne方法不會被自動調用

      True:有信號,子線程的WaitOne方法會被自動調用

   Reset ():將事件狀態設置爲非終止狀態,導致線程阻止;如果該操作成功,則返回true;否則,返回false。

   Set ():將事件狀態設置爲終止狀態,允許一個或多個等待線程繼續;如果該操作成功,則返回true;否則,返回false。

   WaitOne(): 阻止當前線程,直到收到信號。

   WaitOne(TimeSpan, Boolean) :阻止當前線程,直到當前實例收到信號,使用 TimeSpan 度量時間間隔並指定是否在等待之前退出同步域。   

     WaitAll():等待全部信號。

代碼案例  引自:案例來源

static void Main()
        {
            Request req = new Request();

            //線程1幹活
            Thread GetCarThread = new Thread(new ThreadStart(req.InterfaceA));
            GetCarThread.Start();
            //線程2幹活
            Thread GetHouseThead = new Thread(new ThreadStart(req.InterfaceB));
            GetHouseThead.Start();

            //等待三件事都幹成的通知信息  
            AutoResetEvent.WaitAll(req.autoEvents);

            //這個人就開心了。  
            req.InterfaceC();

            System.Console.ReadKey();
        }
public class Request
    {
        //建立事件數組  
        public AutoResetEvent[] autoEvents = null;

        public Request()
        {
            autoEvents = new AutoResetEvent[]
            {
                new AutoResetEvent(false),
                new AutoResetEvent(false)
            };
        }

        public void InterfaceA()
        {
            System.Console.WriteLine("請求A接口");

            Thread.Sleep(1000*2);

            autoEvents[0].Set();

            System.Console.WriteLine("A接口完成");
        }

        public void InterfaceB()
        {
            System.Console.WriteLine("請求B接口");

            Thread.Sleep(1000 * 1);

            autoEvents[1].Set();

            System.Console.WriteLine("B接口完成");
        }

        public void InterfaceC()
        {
            System.Console.WriteLine("兩個接口都已經請求完,正在處理C");
        }
    }

以上是本篇全部內容,請指正;

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