zoukankan      html  css  js  c++  java
  • AutoResetEvent和ManualResetEvent的区别和用法简介

    在.Net多线程编程中,AutoResetEvent和ManualResetEvent这两个类经常用到,用于线程之间的通信, 他们的用法很类似,但也有区别。Set方法将信号置为发送状态,Reset方法将信号置为不发送状态;WaitOne方法在无信号状态下,可以使当前线程挂起;注意这里说的是当前线程。可以通过构造函数的参数值来决定其初始状态,true表示畅通无阻的状态(signaled),线程不能阻塞,即使调用WaitOne也不能阻塞;false表示是可阻塞的状态(nonsignaled),可以调用WaitOne方法来阻塞,WaitOne方法被调用后,当前线程(即调用这个方法的线程)暂停运行(可以看做等待事件触发),直到事件被触发(即另外的线程调用了它的Set方法)。WaitOne阻塞当前线程直到别的线程调用Set方法,但只有ManualResetEvent的状态是可阻塞(nonsignaled)时,WaitOne才能真正的起到作用。不管之前是什么状态,调用Reset都把状态设置为阻塞的(nonsignaled)。其区别就在调用后,AutoResetEvent.WaitOne()每次只允许一个线程进入,当某个线程得到信号后,AutoResetEvent会自动又将信号置为不发送状态,则其他调用WaitOne的线程只有继续等待.也就是说,AutoResetEvent一次只唤醒一个线程;而ManualResetEvent则可以唤醒多个线程,因为当某个线程调用了ManualResetEvent.Set()方法后,其他调用WaitOne的线程获得信号得以继续执行,而ManualResetEvent不会自动将信号置为不发送。也就是说,除非手工调用了ManualResetEvent.Reset()方法,则ManualResetEvent将一直保持有信号状态,ManualResetEvent也就可以同时唤醒多个线程继续执行。

    在多线程的代码里,可以使用一个ManualResetEvent对象来控制线程所有线程;只要在调用WaitOne()方法前,调用Reset()方法,因为WaitOne()控制的是当前线程;但是这样做,ManualResetEvent对象的管理逻辑会变得复杂;所以这里建议一条线程一个ManualResetEvent对象。

    namespace ResetEventTest
    {
        class Program
        {
            private static ManualResetEvent evt = new ManualResetEvent(true);

            static void Main(string[] args)
            {
                Boy sender = new Boy(evt);
                Thread th = new Thread(new ThreadStart(sender.SendFlower));
                th.Start();
                Console.WriteLine("送花途中,我等待");
                evt.Reset();
                evt.WaitOne();      //等待工作,阻塞线程
                Console.WriteLine("收到了吧,是我送的");
                Console.ReadLine();
            }
        }

        public class Boy
        {
            ManualResetEvent evt;

            public Boy(ManualResetEvent _evt)
            {
                evt = _evt;
            }

            public void SendFlower()
            {
                Console.WriteLine("正在送花途中");
                for (int i = 0; i < 10; i++)
                {
                    Thread.Sleep(500);
                    Console.Write(".");
                }
                Console.WriteLine("\r\n花已经送到MM手中^_^");
                evt.Set();  //通知阻塞程序
            }
        }
    }

    ========================================================

    namespace TestMoreResetEvent
    {
        class Program
        {
            static void Main(string[] args)
            {
                EventWaitTest zhangsan = new EventWaitTest("张三");
                EventWaitTest lisi = new EventWaitTest("李四");

                Thread t1 = new Thread(new ThreadStart(zhangsan.Consume));
                Thread t2 = new Thread(new ThreadStart(lisi.Consume));
                Thread t3 = new Thread(new ThreadStart(EventWaitTest.Product));

                t1.Start();
                t2.Start();
                t3.Start();

                Console.Read();
            }
        }

        public class EventWaitTest
        {
            private string name; //顾客姓名  
            //private static AutoResetEvent eventWait = new AutoResetEvent(false);  
            private static ManualResetEvent eventWait = new ManualResetEvent(false);
            private static ManualResetEvent eventOver = new ManualResetEvent(false);

            public EventWaitTest(string name)
            {
                this.name = name;
            }

            public static void Product()
            {
                Console.WriteLine("服务员:厨师在做菜呢,两位稍等");
                Thread.Sleep(2000);
                Console.WriteLine("服务员:宫爆鸡丁好了");
                eventWait.Set();
                while (true)
                {
                    if (eventOver.WaitOne(1000, false))
                    {
                        Console.WriteLine("服务员:两位请买单");
                        eventOver.Reset();
                    }
                }
            }

            public void Consume()
            {
                while (true)
                {
                    if (eventWait.WaitOne(1000, false))
                    {
                        Console.WriteLine(this.name + ":开始吃宫爆鸡丁");
                        Thread.Sleep(2000);
                        Console.WriteLine(this.name + ":宫爆鸡丁吃光了");
                        eventWait.Reset();
                        eventOver.Set();
                        break;
                    }
                    else
                    {
                        Console.WriteLine(this.name + ":等着上菜无聊先玩会手机游戏");
                    }
                }
            }
        } 
    }

     ===============================================================

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;

    namespace ConsoleApplication1
    {
        class Program
        {
            static ManualResetEvent auto = new ManualResetEvent(false);

            static void Main(string[] args)
            {
                Thread t = new Thread(WaitFoSingalToWrite);
                t.Start();
                Thread t1 = new Thread(WaitFoSingalToPlay);
                t1.Start();
                Thread.Sleep(2000);
                auto.Set();
                Console.WriteLine("Main End...");
                Console.ReadLine();
            }

            static void WaitFoSingalToWrite()
            {
                Console.WriteLine("do in...");
                auto.WaitOne();
                Console.WriteLine("do sth..." + DateTime.Now);
                auto.WaitOne(3000, true);
                Console.WriteLine("do sth 1..." + DateTime.Now);
                Console.WriteLine("do out...");
            }

            static void WaitFoSingalToPlay()
            {
                Console.WriteLine("Play in...");
                auto.WaitOne();
                Console.WriteLine("Play sth..." + DateTime.Now);
                auto.WaitOne(3000, true);
                Console.WriteLine("Play sth 1..." + DateTime.Now);
                Console.WriteLine("Play out...");
            }
        }
    }

  • 相关阅读:
    菜鸟浅谈软件开发项目管理
    中国准货币体系的概要简析
    使用dockercompose安装wordpress
    货币乘数
    安全测试的相关内容
    TCP三次握手和四次挥手
    HTTP协议相关
    描述浏览器登录的过程
    AJAX相关知识
    什么是热钱
  • 原文地址:https://www.cnblogs.com/junior/p/2353685.html
Copyright © 2011-2022 走看看