C#總結(一)AutoResetEvent的使用介紹(用AutoResetEvent實現同步)


  前幾天碰到一個線程的順序執行的問題,就是一個異步線程往A接口發送一個數據請求。另外一個異步線程往B接口發送一個數據請求,當A和B都執行成功了,再往C接口發送一個請求。說真的,一直做BS項目,對線程了解,還真不多。就知道AutoResetEvent這個東西和線程有關,用於處理線程切換之類,於是決定用AutoResetEvent來處理上面的問題。
 
  於是網上查找相關資料:
 
  原來,AutoResetEvent在.Net多線程編程中,經常用到。當 某個線程調用WaitOne方法后,信號處於發送狀態,該線程會得到信號, 程序就會繼續向下執行,否則就等待。而且 AutoResetEvent.WaitOne()每次只允許一個線程進入,當某個線程得到信號后,AutoResetEvent會自動又將信號置為不發送狀態,其他調用WaitOne的線程只有繼續等待.也就是說,AutoResetEvent一次只喚醒一個線程,其他線程還是堵塞。
 
  簡介
 
   AutoResetEvent(bool initialState):構造函數,用一個指示是否將初始狀態設置為終止的布爾值初始化該類的新實例。
        false:無信號,子線程的WaitOne方法不會被自動調用
        true:有信號,子線程的WaitOne方法會被自動調用
   Reset ():將事件狀態設置為非終止狀態,導致線程阻止;如果該操作成功,則返回true;否則,返回false。
   Set ():將事件狀態設置為終止狀態,允許一個或多個等待線程繼續;如果該操作成功,則返回true;否則,返回false。
   WaitOne(): 阻止當前線程,直到收到信號。
   WaitOne(TimeSpan, Boolean) :阻止當前線程,直到當前實例收到信號,使用 TimeSpan 度量時間間隔並指定是否在等待之前退出同步域。   
     WaitAll():等待全部信號。
 
  實現
      
 class Program
    {

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

            //這個人去干三件大事  
            Thread GetCarThread = new Thread(new ThreadStart(req.InterfaceA));
            GetCarThread.Start();

            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");
        }
    }

 

  注意,WaitOne 或是WaitAll 最好都加上超時時間。否則沒有收到信號,線程一直會阻塞。
 
  后話
 
  這個只是上面的場景的一個簡化,主要是用來解決剛剛我說的那個場景的問題。
  以上是自己對 AutoResetEvent 的使用總結。不足之處請各位指點一二。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM