zoukankan      html  css  js  c++  java
  • 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(); } }
    复制代码

     备注:信号量

  • 相关阅读:
    nginx实现请求的负载均衡 + Keep Alive实现nginx的高可用
    理解什么是JWT(Json web token)及Python实现
    TCP/UDP协议到底是什么
    Redis实现分布式单点登录
    Python面试题---给定一个字符串 {xxx[xxx{xxx}]xx{x[xxx]xxx{xxx}xx}x} 判断其中的 {}[]() 是否成对出现
    Typora里面如何快捷改变字体颜色?
    基于Docker安装关系型数据库PostgrelSQL替代Mysql
    PEP8-Python编码规范
    欢迎来到我的友链小屋
    windows下lib和dll区别
  • 原文地址:https://www.cnblogs.com/zxtceq/p/7778968.html
Copyright © 2011-2022 走看看