C#AutoResetEvent和ManualResetEvent的區別


一:終止狀態和非終止狀態

    首先說說線程的終止狀態和非終止狀態。AutoResetEvent和ManualResetEvent的構造函數中,都有bool變量來指明線程的終止狀態和非終止狀態。true表示終止狀態(個人理解也就是可運行狀態,根據理解應該是該線程的阻塞終止了),false表示非終止狀態。

 
        AutoResetEvent _autoResetEvent = new AutoResetEvent(false);

        private void BT_Temp_Click(object sender, RoutedEventArgs e) 
        { 
            Thread t1 = new Thread(this.Thread1Foo); 
            t1.Start(); 
            Thread.Sleep(3000); //Thread.Sleep(Int32)是批當前進程掛起3000毫秒,與線程t1是一點關系也沒有的。
            _autoResetEvent.Set(); 
        }

        void Thread1Foo() 
        { 
            _autoResetEvent.WaitOne(); 
            MessageBox.Show("t1 end"); 
        } 
    這段代碼的執行結果,就是3秒鍾過后,彈出“t1 end”。 
    而如果把: 
    AutoResetEvent _autoResetEvent = new AutoResetEvent(false); 
    改為: 
    AutoResetEvent _autoResetEvent = new AutoResetEvent(true); 
    則“t1 end”將會立刻彈出。 
    也就是說,在終止狀態中,_autoResetEvent.WaitOne()是不會起到阻滯工作線程的作用的。(PS:ManualResetEvent也同樣)

二:AutoResetEvent和ManualResetEvent的區別 

       AutoResetEvent 允許線程通過發信號互相通信。 通常,當線程需要獨占訪問資源時使用該類。

       線程通過調用 AutoResetEvent 上的 WaitOne 來等待信號。 如果 AutoResetEvent 為非終止狀態,則線程會被阻止,並等待當前控制資源的線程通過調用 Set來通知資源可用。

       調用 Set 向 AutoResetEvent 發信號以釋放等待線程。 AutoResetEvent 將保持終止狀態,直到一個正在等待的線程被釋放,然后自動返回非終止狀態。 如果沒有任何線程在等待,則狀態將無限期地保持      為終止狀態如果當 AutoResetEvent 為終止狀態時線程調用 WaitOne,則線程不會被阻止。 AutoResetEvent 將立即釋放線程並返回到非終止狀態

 




     AutoResetEvent _autoResetEvent = new AutoResetEvent(false); 
        private void BT_Temp_Click(object sender, RoutedEventArgs e) 
        { 
            Thread t1 = new Thread(this.Thread1Foo); 
            t1.Start(); 
            Thread t2 = new Thread(this.Thread2Foo); 
            t2.Start(); 
            Thread.Sleep(3000); 
            _autoResetEvent.Set(); 
        }

        void Thread1Foo() 
        { 
            _autoResetEvent.WaitOne(); 
            MessageBox.Show("t1 end"); 
        }

        void Thread2Foo() 
        { 
            _autoResetEvent.WaitOne(); 
            MessageBox.Show("t2 end"); 
        } 
    該段代碼運行的效果是,過3秒后,要么彈出“t1 end”,要么彈出“t2 end”,不會兩個都彈出。也就是說,其中一個進行將會結束,而另一個進程永遠不會結束。

代碼段3: 
        ManualResetEvent _menuRestEvent = new ManualResetEvent(false);

        private void BT_Temp_Click(object sender, RoutedEventArgs e) 
        { 
            Thread t1 = new Thread(this.Thread1Foo); 
            t1.Start(); 
            Thread t2 = new Thread(this.Thread2Foo); 
            t2.Start(); 
            Thread.Sleep(3000); 
            _menuRestEvent.Set(); 
        }

        void Thread1Foo() 
        { 
            _menuRestEvent.WaitOne(); 
            MessageBox.Show("t1 end"); 
        }

        void Thread2Foo() 
        { 
            _menuRestEvent.WaitOne(); 
            MessageBox.Show("t2 end"); 
        } 
    該段代碼運行的效果是,過3秒后,“t1 end”和“t2 end”,兩個都被彈出。也就是說,兩個進程都結束了。 
    這個特性就是說,AutoResetEvent只會給一個線程發送信號,而不會給多個線程發送信號。在我們需要同步多個線程的時候,就只能采用ManualResetEvent了。至於深層次的原因是,AutoResetEvent在set()之后,會將線程     狀態自動置為false,而ManualResetEvent在Set()后,線程的狀態就變為true了,必須手動ReSet()之后,才會重新將線程置為false。這也就是為什么他們的名字一個為Auto,一個為Manual的原因。為了更加充分的驗證Manua  lResetEvent的這點特性,我們再來看代碼片段4

代碼片段4: 
    ManualResetEvent _menuRestEvent = new ManualResetEvent(false);

        private void BT_Temp_Click(object sender, RoutedEventArgs e) 
        { 
            Thread t1 = new Thread(this.Thread1Foo); 
            t1.Start(); 
            Thread t2 = new Thread(this.Thread2Foo); 
            t2.Start(); 
            Thread.Sleep(3000); 
            _menuRestEvent.Set(); 
            //_menuRestEvent.Reset();            
        }

        void Thread1Foo() 
        { 
            _menuRestEvent.WaitOne(); 
            MessageBox.Show("t1 step1 end"); 
            //睡1S,用於等待主線程_menuRestEvent.Reset(); 
            Thread.Sleep(1000); 
            _menuRestEvent.WaitOne(); 
            MessageBox.Show("t1 step2 end"); 
        }

        void Thread2Foo() 
        { 
            _menuRestEvent.WaitOne(); 
            MessageBox.Show("t2 step1 end"); 
            //睡1S,用於等待主線程_menuRestEvent.Reset(); 
            Thread.Sleep(1000); 
            _menuRestEvent.WaitOne(); 
            MessageBox.Show("t2 step2 end"); 
        } 
    在代碼片段4中,我們對//_menuRestEvent.Reset()進行了注釋,也就是說, _menuRestEvent.Set()后,線程的狀態就是true狀態的,程序運行的結果是"t1 step1 end"、"t1 step2 end"、"t1 step2 end"、"t2 step2 end"在3秒之后全部彈出。
    而如果我們將//_menuRestEvent.Reset()的注釋去掉,會發現"t1 step2 end"和"t2 step2 end"永遠不會彈出。除非我們在主線程中再次對_menuRestEvent進行Set()。

  


免責聲明!

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



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