AutoResetEvent用于线程间的同步

Test.cs代码:

class Test
{
//构造函数,用一个指示是否将初始状态设置为终止的布尔值初始化该类的新实例。
//false:无信号,子线程的WaitOne方法不会被自动调用
//true:有信号,子线程的WaitOne方法会被自动调用

//在.Net多线程编程中,AutoResetEvent和ManualResetEvent这两个类经常用到, 他们的用法很类似,但也有区别。Set方法将信号置为发送状态,Reset方法将信号置为不发送状态,WaitOne等待信号的发送。可以通过构造函数的参数值来决定其初始状态,若为true则非阻塞状态,为false为阻塞状态。如果某个线程调用WaitOne方法,则当信号处于发送状态时,该线程会得到信号, 继续向下执行。其区别就在调用后,AutoResetEvent.WaitOne()每次只允许一个线程进入,当某个线程得到信号后,AutoResetEvent会自动又将信号置为不发送状态,则其他调用WaitOne的线程只有继续等待.也就是说,AutoResetEvent一次只唤醒一个线程;而ManualResetEvent则可以唤醒多个线程,因为当某个线程调用了ManualResetEvent.Set()方法后,其他调用WaitOne的线程获得信号得以继续执行,而ManualResetEvent不会自动将信号置为不发送。也就是说,除非手工调用了ManualResetEvent.Reset()方法,则ManualResetEvent将一直保持有信号状态,ManualResetEvent也就可以同时唤醒多个线程继续执行。

//本质上AutoResetEvent.Set()方法相当于ManualResetEvent.Set()+ManualResetEvent.Reset();
//因此AutoResetEvent一次只能唤醒一个线程,其他线程还是堵塞
private static AutoResetEvent _workerEvent = new AutoResetEvent(false);
private static AutoResetEvent _mainEvent = new AutoResetEvent(false);

static void Process(int seconds)
{
Console.WriteLine("②子线程开始长时间运行的工作...");
Thread.Sleep(TimeSpan.FromSeconds(seconds));
Console.WriteLine("③子线程工作完成!");
_workerEvent.Set();

//--------------------------------------------------------

Console.WriteLine("④等待主线程完成其工作");
_mainEvent.WaitOne();

//--------------------------------------------------------

Console.WriteLine("⑧子线程开始第二个操作...");
Thread.Sleep(TimeSpan.FromSeconds(seconds));
Console.WriteLine("⑨子线程第二个操作工作完成!");
//这里是设置为有信号
_workerEvent.Set();
}

//简单来说只有调用Set()方法后才能执行WaitOne()后面的代码,AutoResetEvent和ManualResetEvent分别都有Set()改变为有信号 ,Reset()改变为无信号,WaitOne()将会阻塞当前调用的线程,直到有信号为止,即执行了Set()方法,WaitOne()方法还可以带指定时间的参数。
public static void RunTest()
{
//开启一个处理线程(子线程)
var t = new Thread((() => Process(10)));
t.Start();
Console.WriteLine("①等待一个子线程完成工作");
_workerEvent.WaitOne();
//--------------------------------------------------------

Console.WriteLine("⑤子线程第一个操作完成!");
Console.WriteLine("⑥在主线程上执行操作");
Thread.Sleep(TimeSpan.FromSeconds(5));
//主线程设置为有信号,即通知正在等待的线程有事件发生
_mainEvent.Set();
Console.WriteLine("⑦现在在子线程上运行第二个操作");

//--------------------------------------------------------

//执行到这个地方时,会等待set调用后改变了信号才接着执行
_workerEvent.WaitOne();
Console.WriteLine("⑩子线程第二个操作完成!");
//--------------------------------------------------------
Console.ReadKey();
}
}

class Test
{
//构造函数,用一个指示是否将初始状态设置为终止的布尔值初始化该类的新实例。
//false:无信号,子线程的WaitOne方法不会被自动调用
//true:有信号,子线程的WaitOne方法会被自动调用

//在.Net多线程编程中,AutoResetEvent和ManualResetEvent这两个类经常用到, 他们的用法很类似,但也有区别。Set方法将信号置为发送状态,Reset方法将信号置为不发送状态,WaitOne等待信号的发送。可以通过构造函数的参数值来决定其初始状态,若为true则非阻塞状态,为false为阻塞状态。如果某个线程调用WaitOne方法,则当信号处于发送状态时,该线程会得到信号, 继续向下执行。其区别就在调用后,AutoResetEvent.WaitOne()每次只允许一个线程进入,当某个线程得到信号后,AutoResetEvent会自动又将信号置为不发送状态,则其他调用WaitOne的线程只有继续等待.也就是说,AutoResetEvent一次只唤醒一个线程;而ManualResetEvent则可以唤醒多个线程,因为当某个线程调用了ManualResetEvent.Set()方法后,其他调用WaitOne的线程获得信号得以继续执行,而ManualResetEvent不会自动将信号置为不发送。也就是说,除非手工调用了ManualResetEvent.Reset()方法,则ManualResetEvent将一直保持有信号状态,ManualResetEvent也就可以同时唤醒多个线程继续执行。

//本质上AutoResetEvent.Set()方法相当于ManualResetEvent.Set()+ManualResetEvent.Reset();
//因此AutoResetEvent一次只能唤醒一个线程,其他线程还是堵塞
private static AutoResetEvent _workerEvent = new AutoResetEvent(false);
private static AutoResetEvent _mainEvent = new AutoResetEvent(false);

static void Process(int seconds)
{
Console.WriteLine("②子线程开始长时间运行的工作...");
Thread.Sleep(TimeSpan.FromSeconds(seconds));
Console.WriteLine("③子线程工作完成!");
_workerEvent.Set();

//--------------------------------------------------------

Console.WriteLine("④等待主线程完成其工作");
_mainEvent.WaitOne();

//--------------------------------------------------------

Console.WriteLine("⑧子线程开始第二个操作...");
Thread.Sleep(TimeSpan.FromSeconds(seconds));
Console.WriteLine("⑨子线程第二个操作工作完成!");
//这里是设置为有信号
_workerEvent.Set();
}

//简单来说只有调用Set()方法后才能执行WaitOne()后面的代码,AutoResetEvent和ManualResetEvent分别都有Set()改变为有信号 ,Reset()改变为无信号,WaitOne()将会阻塞当前调用的线程,直到有信号为止,即执行了Set()方法,WaitOne()方法还可以带指定时间的参数。
public static void RunTest()
{
//开启一个处理线程(子线程)
var t = new Thread((() => Process(10)));
t.Start();
Console.WriteLine("①等待一个子线程完成工作");
_workerEvent.WaitOne();
//--------------------------------------------------------

Console.WriteLine("⑤子线程第一个操作完成!");
Console.WriteLine("⑥在主线程上执行操作");
Thread.Sleep(TimeSpan.FromSeconds(5));
//主线程设置为有信号,即通知正在等待的线程有事件发生
_mainEvent.Set();
Console.WriteLine("⑦现在在子线程上运行第二个操作");

//--------------------------------------------------------

//执行到这个地方时,会等待set调用后改变了信号才接着执行
_workerEvent.WaitOne();
Console.WriteLine("⑩子线程第二个操作完成!");
//--------------------------------------------------------
Console.ReadKey();
}
}
---------------------

作者:风灵使
来源:CSDN
原文:https://blog.csdn.net/wulex/article/details/53932598
版权声明:本文为博主原创文章,转载请附上博文链接!

---------------------

【AutoResetEvent】的更多相关文章

  1. C#异步的世界【上】

    新进阶的程序员可能对async.await用得比较多,却对之前的异步了解甚少.本人就是此类,因此打算回顾学习下异步的进化史. 本文主要是回顾async异步模式之前的异步,下篇文章再来重点分析async ...

  2. [转]C#异步的世界【上】

    阅读目录   APM EAP TAP 延伸思考 新进阶的程序员可能对async.await用得比较多,却对之前的异步了解甚少.本人就是此类,因此打算回顾学习下异步的进化史. 本文主要是回顾async异 ...

  3. 【转】C#异步的世界【上】

    [转]C#异步的世界[上] 新进阶的程序员可能对async.await用得比较多,却对之前的异步了解甚少.本人就是此类,因此打算回顾学习下异步的进化史. 本文主要是回顾async异步模式之前的异步,下 ...

  4. C#异步的世界【上】(转)

    新进阶的程序员可能对async.await用得比较多,却对之前的异步了解甚少.本人就是此类,因此打算回顾学习下异步的进化史. 本文主要是回顾async异步模式之前的异步,下篇文章再来重点分析async ...

  5. Python高手之路【六】python基础之字符串格式化

    Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存.[PEP-3101] This ...

  6. 【原】谈谈对Objective-C中代理模式的误解

    [原]谈谈对Objective-C中代理模式的误解 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这篇文章主要是对代理模式和委托模式进行了对比,个人认为Objective ...

  7. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  8. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

  9. 【调侃】IOC前世今生

    前些天,参与了公司内部小组的一次技术交流,主要是针对<IOC与AOP>,本着学而时习之的态度及积极分享的精神,我就结合一个小故事来初浅地剖析一下我眼中的“IOC前世今生”,以方便初学者能更 ...

随机推荐

  1. HIVE-利用ow_number() OVER(PARTITION BY)函数介绍求TOP-K

    http://blog.csdn.net/631799/article/details/7419797 第一句话: select row_number() over (partition by mon ...

  2. 3.Monkey Script小案例

    1.实现打开搜狗搜索APP,在搜索框输入内容,点击回车,重复2次运行 2.实现代码如下所示: type=user count=10 speed=1.0 start data >> Laun ...

  3. 二:HTML文本编译器 kindeditor-4.1.10 的使用 SpringMVC+jsp的实现

    这和一篇与上一篇的区别在与,上一篇是直接请求到action我们剩下的都是我们全部手动处理, 而这一片篇是由kindeditor内部处理,图片上传到本地,基本上没什么区别,但是有一点一定要注意的就是,这 ...

  4. 机器学习:集成学习(Soft Voting Classifier)

    一.Hard Voting 与 Soft Voting 的对比 1)使用方式 voting = 'hard':表示最终决策方式为 Hard Voting Classifier: voting = 's ...

  5. 杂项:UUID

    ylbtech-杂项:UUID UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写,是一种软件建构的标准,亦为开放软件基金会组织在分布式计算环境领域的一部 ...

  6. 版本管理 word 文档比较

    1.因为公司还在用SVN, 2.而且 还在用word 写文档, 3.而且 commit log 基本不写, 所以导致,想了解word文档 改动, 很浪费时间!!!! 所以想 快速了解word 改动, ...

  7. python web框架 Django进阶

    django 进阶 基础中,一些操作都是手动创建连接的非主流操作,这样显得太low,当然也是为了熟悉这个框架! 实际中,django自带连接数据库和创建app的机制,同时还有更完善的路由系统机制.既然 ...

  8. 2016.2.24 利用用户控件和委托完美解决快速选择txbbox

    1.首先将tet_box和一个datagridview控件打包成用户控件uC_QuickTxtBox 2.在用户控件中定义执行主窗口的委托函数 3.主窗体中添加用户控件的load事件,赋值 uC_Qu ...

  9. Drools学习笔记4—Consequence/RHS

    Right Hand Side,当LHS所有条件满足才会执行 可以使用LHS部分定义的绑定变量.全局变量.或者直接编写JAVA代码. 提供宏函数操作working memory fact对象,如ins ...

  10. java 多线程系列基础篇(二)

    概要 本章,我们学习“常用的实现多线程的2种方式”:Thread 和 Runnable.之所以说是常用的,是因为通过还可以通过java.util.concurrent包中的线程池来实现多线程.关于线程 ...