博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# ManualResetEvent和AutoResetEvent 使用笔记
阅读量:6228 次
发布时间:2019-06-21

本文共 2682 字,大约阅读时间需要 8 分钟。

一、两者区别

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();        }    }

 备注:信号量

转载地址:http://qejna.baihongyu.com/

你可能感兴趣的文章
使用VS GDB扩充套件在VS上远端侦错Linux上的C/C++程序
查看>>
求助关于asp.net里使用ocx控件的问题
查看>>
asp.net生成条形码
查看>>
线段树基本格式
查看>>
springmvc集成shiro例子
查看>>
ionic2.1.0 --beta3版本新建页面做弹框时遇到的问题
查看>>
一个简单例子阐明while True与if的配合使用方法
查看>>
Generate Parentheses
查看>>
最短路径2
查看>>
[LeetCode]Search a 2D Matrix
查看>>
Hadoop学习之旅三:MapReduce
查看>>
Exception: Could not bind to 0.0.0.0:8080 after trying for 30 seconds
查看>>
C语言函数指针(转载)
查看>>
Walls and Gates
查看>>
js实现拖动,刚学js时写的
查看>>
在Mac mini上编译Android源码
查看>>
在.Net中进行SQL Server数据库备份与还原操作实用类
查看>>
yum被锁定
查看>>
时钟制作
查看>>
php-用$this变量访问方法和属性
查看>>