C#——ManualResetEvent的理解和用法


    先了解一下ManualResetEvent的基本用法:

1、初始化:public ManualResetEvent(bool initialState);

  ManualResetEvent的構造方法有個bool型參數,當為true時,則表示有信號,為false時,則表示無信號。

      這個怎么理解呢?我們接着看ManualResetEvent3個基本方法中的WaitOne方法。

2、WaitOne方法:WaitOne方法有幾種4種重載,我在這里只對它的功能進行分析。

  WaitOne方法,顧名思義,它會具有一種等待的功能,也就是線程阻塞。

      這里的阻塞功能是有條件的,當無信號時,它是阻塞的,有信號時,它將無任何阻塞,被執行時就直接跳過了。

       所以,回顧到1,當初始化ManualResetEvent時,initialState為false,WaitOne將會有阻塞效果,否則,沒有阻塞效果。

3、Set方法:將ManualResetEvent對象的信號狀態設為有信號狀態,

     這個時候WaitOne如果正在阻塞中的話,將會立即終止阻塞,向下繼續執行。

     而且這個狀態一直不變的話,每次執行到WaitOne都將無任何阻塞。

4、Reset方法:

     將ManualResetEvent對象的信號狀態設為無信號狀態,當下次執行到WaitOne時,又將重新開始阻塞。

復制代碼
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ThreadTest
{
    class Program
    {
        static void Main(string[] args)
        {
            new ProductAndCostTester();
        }
    }

    /// <summary>
    /// 生產消費模型
    /// </summary>
    public class ProductAndCostTester
    {
        /// <summary>
        /// 生產線1線程
        /// </summary>
        private Thread _producterThread1;
        /// <summary>
        /// 生產線2線程
        /// </summary>
        private Thread _producterThread2;
        /// <summary>
        /// 消費線線程
        /// </summary>
        private Thread _costerThread;
        /// <summary>
        /// 產品列表
        /// </summary>
        private List<int> _goodList;
        /// <summary>
        /// ManualResetEvent實例
        /// </summary>
        private ManualResetEvent _mre;

        public ProductAndCostTester()
        {
            _goodList = new List<int>();

            _mre = new ManualResetEvent(false);//false初始化狀態為無信號,將使WaitOne阻塞

            _producterThread1 = new Thread(Product1);
            _producterThread1.Name = "Productor1";
            _producterThread1.Start();

            _producterThread2 = new Thread(Product2);
            _producterThread2.Name = "Productor2";
            _producterThread2.Start();

            _costerThread = new Thread(Cost);
            _costerThread.Name = "Costor";
            _costerThread.Start();
        }

        /// <summary>
        /// 生產線1
        /// </summary>
        void Product1()
        {
            while (true)
            {
                Console.WriteLine(Thread.CurrentThread.Name + ":" + DateTime.Now.ToString("HH:mm:ss"));
                for (int i = 0; i < 3; i++)
                {
                    _goodList.Add(1);
                }
                _mre.Set();//表示有信號了,通知WaitOne不再阻塞

                Thread.Sleep(8000);
            }
        }

        /// <summary>
        /// 生產線2
        /// </summary>
        void Product2()
        {
            while (true)
            {
                Console.WriteLine(Thread.CurrentThread.Name + ":" + DateTime.Now.ToString("HH:mm:ss"));
                for (int i = 0; i < 6; i++)
                {
                    _goodList.Add(1);
                }
                _mre.Set();//表示有信號了,通知WaitOne不再阻塞

                Thread.Sleep(10000);
            }
        }

        /// <summary>
        /// 消費線
        /// </summary>
        void Cost()
        {
            while (true)
            {
                if (_goodList.Count > 0)
                {
                    Console.WriteLine("Cost " + _goodList.Count + " at " + DateTime.Now.ToString("HH:mm:ss"));
                    _goodList.Clear();
                    _mre.Reset();//重置為無信號了,使WaitOne可以再次阻塞
                }
                else
                {
                    Console.WriteLine("No cost at " + DateTime.Now.ToString("HH:mm:ss"));
                    _mre.WaitOne();//如果沒有可消費的產品,即無信號,則會阻塞
                }
            }
        }
    }
}
復制代碼

 


免責聲明!

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



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