C# ManualResetEvent和AutoResetEvent 使用筆記


一、兩者區別

1.ManualResetEvent 調用一次Set()后將允許恢復所有被阻塞線程。需手動在調用WaitOne()之后調用Reset()重置信號量狀態為非終止,然后再次調用WaitOne()的時候才能繼續阻塞線程,反之則不阻塞

2.AutoResetEvent,調用一次Set()只能繼續被阻塞的一個線程,多次調用Set()才行,但不需手動調用Reset();再次調用WaitOne()的時候又能阻塞線程,也是和前者的區別

3.兩者單個實例均可阻塞一個或多個線程,在多個線程中調用 主線程 創建的 兩者單個實例.WaitOne(),前提是兩者實例必須是非終止狀態

4.兩者實例化構造參數解釋

public AutoResetEvent(bool initialState);

true:設置終止狀態。相當於調用了Set(),即首次不會被WaitOne()阻塞,下次執行WaitOne()才會被阻塞

false:設置非終止狀態。遇到WaitOne()立即阻塞所在的一個或多個線程

5. 兩者都只會阻塞WaitOne()所在的線程,WaitOne()可被多個線程調用

 

二、在哪里創建信號量實例?

  一般情況下在工作線程中創建信號量的實例,在其他線程中使用,然后再在工作線程中調用Set(),可以是在非主線程創建實例

 

三、代碼示例

   public  class Program
    {

        //1.AutoResetEvent,調用一次Set()只能繼續一個阻塞線程
        //2.AutoResetEvent調用Set()后自動Reset()
        static void Main(string[] args)
        {

            Thread t = null;
            AutoResetEvent Event = new AutoResetEvent(false);

            for (int i = 0; i < 2; i++)
            {
                t = new Thread(() =>
                {

                    while (true)
                    {
                        //阻塞當前線程
                        Event.WaitOne();
                        Console.WriteLine("我是線程:" + Thread.CurrentThread.Name);
                        Thread.Sleep(1000);
                    }

                });
                t.Name = i + "";
                t.Start();
            }
            //5秒后允許一個等待的線程繼續。當前允許的是線程1
            Thread.Sleep(5000);
            Event.Set();

            //5秒后允許一個等待的線程繼續。當前允許的是線程2
            Thread.Sleep(5000);
            Event.Set();

            //PS:如果使用AutoResetEvent的WaitOne()將5個線程阻塞,則需要調用5次Set()才能恢復5;如果再次阻塞時,不需要手動調用Reset();
            Console.ReadLine();

        }


        //1.ManualResetEvent,調用一次Set()允許繼續全部阻塞線程,這是和AutoResetEvent的區別
        //2.ManualResetEvent調用Set()后需要手動Reset(),將信號 設置為非終止狀態,只有非終止狀態線程中調用WaitOne()才能導所在的致線程阻止。
        static void Main2(string[] args)
        {

            Thread t = null;
            //初始化非終止狀態,WaitOne()可以直接阻塞所在的線程
            ManualResetEvent Event = new ManualResetEvent(false);

            for (int i = 0; i < 2; i++)
            {
                t = new Thread(() =>
                {

                    while (true)
                    {
                       //阻塞當前線程
                        Event.WaitOne();
                        Console.WriteLine("我是線程:" + Thread.CurrentThread.Name);
Event.ReSet(); Thread.Sleep(
1000); } }); t.Name = i + ""; t.Start(); } //5秒后允許所有阻塞的線程繼續。 Thread.Sleep(5000); Event.Set(); //PS:如果使用ManualResetEvent將5個線程阻塞,則需要調用1次Set(),將允許所有阻塞的線程繼續執行;如果再次阻塞時,則需要手動調用Reset(); Console.ReadLine(); } }

 備注:信號量

 


免責聲明!

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



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