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. bzoj 5092 [Lydsy1711月赛]分割序列——高维前缀和

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5092 套路地弄一个前缀异或和,就变成 f[ i ]=max_{j=0}^{i} { s[ j ...

  2. PKU campus 2018 A Wife——差分约束?/dp

    题目:http://poj.openjudge.cn/campus2018/A 有正规的差分约束做法,用到矩阵转置等等. 但也有简单(?)的dp做法. 有一个结论(?):一定要么在一天一点也不选,要么 ...

  3. why latches are considered bad?

    A "latch" is different from a "Flip-Flop" in that a FF only changes its output i ...

  4. linux下安装composer

    在linux下使用comoser命令,但是提示composer command not found 那么就是当前环境中没有composer 学习源头: https://blog.csdn.net/gb ...

  5. Hanoi双塔问题(递推)

    Hanoi双塔问题 时间限制: 1 Sec  内存限制: 128 MB提交: 10  解决: 4[提交][状态][讨论版][命题人:外部导入] 题目描述 给定A,B,C三根足够长的细柱,在A柱上放有2 ...

  6. python中的 ' ' 和 " "

    #!/usr/bin/python import MySQLdb try: conn = MySQLdb.connect(host = 'localhost', user = 'root', pass ...

  7. 图解缓存淘汰算法三之FIFO

    1.概念分析 FIFO(First In First Out),即先进先出.最先进入的数据,最先出来.一个很简单的算法.只要使用队列数据结构即可实现.那么FIFO淘汰算法基于的思想是"最近刚 ...

  8. 破解Mac版MyEclipse-2017-ci3 2017、11、21亲测有效

    一.前提 要有安装好的jdk,没有的Mac用户看这篇博客:给Mac安装最新版本的jdk(戳此)  Windows用户先去官网(戳此)下载jdk,然后百度”jdk配置环境变量”(戳此),很简单的,加油你 ...

  9. 修改linux内核启动logo及显示位置

    转载于:http://blog.chinaunix.net/uid-28458801-id-3484269.html 在此基础上我又添加了我的一些不同的地方,仅供参考 内核版本: 2.6.35.3 l ...

  10. Android中同一个ImageView中根据状态显示不同图片

    一般: if(条件1) { image.setBackground(R.id.xxx1); } else if (条件2) { image.setBackground(R.id.xxx2); } 实际 ...