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. Python 算法之冒泡排序

    冒泡排序 冒泡排序算法的原理如下:(从后往前) 1.比较相邻的元素.如果第一个比第二个大,就交换他们两个. 2.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是 ...

  2. 机器学习:模型泛化(岭回归:Ridge Regression)

    一.基础理解 模型正则化(Regularization) # 有多种操作方差,岭回归只是其中一种方式: 功能:通过限制超参数大小,解决过拟合或者模型含有的巨大的方差误差的问题: 影响拟合曲线的两个因子 ...

  3. IIS:template

    ylbtech-IIS: 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部     6.返回顶部   7.返回顶部   8.返回顶部   9.返回顶部   10.返 ...

  4. altium designer 中器件原理图库中,将一个器件分成几部分是如何操作的?就是如何用part表示?

    在SCH Library的Components中选中你要添加part的器件,tools菜单--new part即可

  5. 构建工具:webpack与grunt/gulp

    1.    webpack 官网:http://webpack.github.io/docs/ 中文文档:http://www.css88.com/doc/webpack2/ Webpack 是一个模 ...

  6. form(去掉关闭按钮,禁止调整大小)

    禁止Form窗口调整大小方法:FormBorderStyle 设为FixedSingle: 不能使用最大化窗口: MaximuzeBox 设为False: 不能使用最小化窗口:   MinimizeB ...

  7. tomcat中间件配置说明

    因为Tomcat 技术先进.性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器.目前最新版本是8.0. 方法/步骤   一.tomca ...

  8. ABP仓储

    简介 我们都知道ABP已经实现了仓储模式,支持EF core 和dapper 进行数据库的连接和管理,可以很方便的注入仓储来操作你的数据,不需要自己单独定义一个仓储来实现,通用的仓储实现了通用的cru ...

  9. 从文件中读取yuv和h264数据

    1.从文件中读取h264数据 参考ffmpeg avc.c写的从文件中一帧帧读取h.264数据的demo #include <stdio.h> #include <stdlib.h& ...

  10. adb eclipse 截屏

    DDMS  左侧  选中设备 右上角有一个相机样式的按钮"screen capture"