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导入csv文件时,出现SyntaxError

    背景 np.loadtxt()用于从文本加载数据. 文本文件中的每一行必须含有相同的数据. *** loadtxt(fname, dtype=<class 'float'>, commen ...

  2. BZOJ3052:[WC2013]糖果公园

    浅谈莫队:https://www.cnblogs.com/AKMer/p/10374756.html 题目传送门:https://lydsy.com/JudgeOnline/problem.php?i ...

  3. zabbix监控进程

    参考http://chenx1242.blog.51cto.com/10430133/1837990 1 前期说明 zabbix_server查看“文件在后台运行数量”所对应的key就是:proc.n ...

  4. java流类基础练习。

    总结:BufferedReader.InputStreamReader.字节与字符的区别. package com.ds; import java.io.*; //从控制台输入字符串,输到sdd时停止 ...

  5. Web项目安全相关博客日志大集合(仅供学习及参考)

    强制使用HTTPS --- Tomcat篇 ---通过在tomcat/conf/web.xml中进行配置,从而将http自动转为https.(即强制HSTS)http://blog.csdn.net/ ...

  6. nfs cron shell 作业

    作业一: nginx反向代理三台web服务器,实现负载均衡 所有的web服务共享一台nfs的存储 2台服务器 nginx [lb] :101.200.206.6 nginx [web]:101.200 ...

  7. mybatis(非常详细的哦~~~~)

    备注:ibatis 迁入google code 更名为Mybatis 官方文档:http://mybatis.org/mybatis-3/ 比较好的教程推荐:http://www.blogjava.n ...

  8. Ok6410裸机驱动学习(三)C语言内嵌汇编

    1.C语言内嵌汇编使用方法 C内嵌汇编以关键字”_asm_或asm开始,下辖4个部分,各部分之间用“:”分开,第一部分是必须写的,后面3个部分可以省略,但是分号:不能省略 优化后的代码 2.汇编程序框 ...

  9. spring bean属性及子元素使用总结

    spring bean属性及子元素使用总结 2016-08-03 00:00 97人阅读 评论(0) 收藏 举报  分类: Spring&SpringMVC(17)  版权声明:本文为博主原创 ...

  10. Python 面向对象 (进阶篇)

    <Python 面向对象(初级篇)>文章介绍了面向对象基本知识: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使用(可 ...