在多线程开发中,时常用到 ManualResetEvent 与 AutoResetEvent  。 它们如同道路交通中的信号灯。两者之间有什么区别呢?

共同点:

均继承 EventWaitHandle 接口,因此,均具有以下功能:

Reset() //红灯

Set() //绿灯

WaitOne() // 等待信号

不同点:

AutoResetEvent   收到 Set 后 , 一次只能执行一个线程,其它线程继续 WaitOne 。

ManualResetEvent  收到 Set 后,所有处理 WaitOne 状态线程均继续执行。

msdn 提到(如果没有线程 处于WaitOne() 状态,而调用 Set , AutoResetEvent 将保持Set 状态):

调用Set信号AutoResetEvent释放等待线程。 AutoResetEvent 将保持终止状态直到一个等待线程释放,并自动返回到非信号状态。 如果没有线程处于等待状态,状态将无限期地保持已发出信号。

因此通常WatiOne 之前,先 Reset() 一下,清除Set 信号

需要注意的是(两个 Set 调用之间时间较短,第二个 Set 信号可能会丢失,因此连续 Set 调用,中间需要 Sleep 一定时间):

不能保证的每个调用Set方法将释放一个线程。 如果两次调用太靠近在一起,以便第二次调用前释放线程发生,只有一个线程被释放。 就像第二次调用未发生。 此外,如果Set时没有等待的线程调用和AutoResetEvent已终止,则调用不起作用。

有网友说:

AutoResetEvent.Set() = ManualResetEvent.Set() + ManualResetEvent.Reset();

个人理解 ,这只是原理层面含义,实际使用过程中,有差别的,如下示例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace testManualResetEvent
{class Program{static object objManualResetEvent = new object();static System.Threading.ManualResetEvent manu = new System.Threading.ManualResetEvent(false);//static System.Threading.AutoResetEvent manu = new System.Threading.AutoResetEvent(false);static void Main(string[] args){for (int i = 0; i < 10; i++){System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(() => { Product(); }));t.Start();}manu.Set();manu.Reset();Console.ReadKey();}static void Product(){manu.WaitOne(10000);Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);}}
}

实际执行结果 , 在 执行 set 后 reset 前 ,有多少个线程唤起执行,无法预料:

需要加锁 ,确保一次通过一个线程:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace testManualResetEvent
{class Program{static object objManualResetEvent = new object();static System.Threading.ManualResetEvent manu = new System.Threading.ManualResetEvent(false);//static System.Threading.AutoResetEvent manu = new System.Threading.AutoResetEvent(false);static void Main(string[] args){for (int i = 0; i < 10; i++){System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(() => { Product(); }));t.Start();}manu.Set();//System.Threading.Thread.Sleep(100); //连续 set 需要 sleep//manu.Set();//manu.Reset();//System.Threading.Thread.Sleep(100);//manu.Set();//manu.Reset();Console.ReadKey();}static void Product(){lock (objManualResetEvent){manu.WaitOne(10000);manu.Reset();Console.WriteLine(System.Threading.Thread.CurrentThread.ManagedThreadId);}}}
}

执行结果:

C# ManualResetEvent 与 AutoResetEvent 区别相关推荐

  1. c#线程学习之ManualResetEvent和AutoResetEvent的区别!

    AutoResetEvent在.Net多线程编程中经常用到.当某个线程调用WaitOne方法后,信号处于发送状态,该线程会得到信号, 程序就会继续向下执行,否则就等待.而且 AutoResetEven ...

  2. .Net 中 ManualResetEvent 和 AutoResetEvent 的区别

    在 .Net 多线程中可以使用 ManualResetEvent 和 AutoResetEvent 来协调不同的线程的运行.文档中说这两个类都可以通过 set 方法释放信号,等待信号的线程可以通过捕获 ...

  3. C#使用ManualResetEvent和AutoResetEvent处理线程通信

    示例 两个线程交替输出"1 a 2 b 3 c 4 d 5 ....." 代码 //利用ManualResetEvent和AutoResetEvent交替输出"1 a 2 ...

  4. C# 总结ManualResetEvent与AutoResetEvent【一】

    C# 总结ManualResetEvent与AutoResetEvent[一] ManualResetEvent: ManualResetEvent 允许线程通过发信号互相通信.通常,此通信涉及一个线 ...

  5. ManualResetEvent,AutoResetEvent 学习

    AutoResetEvent :通知正在等待的线程已发生事件.无法继承此类. ManualResetEvent:通知一个或多个正在等待的线程已发生事件.无法继承此类. using System; us ...

  6. 多线程间通信之AutoResetEvent和ManualResetEvent的原理分析

    AutoResetEvent 允许线程通过发信号互相通信. 通常,当线程需要独占访问资源时使用该类. 线程通过调用 AutoResetEvent 上的 WaitOne 来等待信号. 如果 AutoRe ...

  7. 【深度好文】多线程之WaitHandle--派生EventWaitHandle事件构造-》AutoResetEvent、ManualResetEvent...

    AutoResetEvent/ManualResetEvent 都是继承自 EventWaitHandle ,EventWaitHandle继承自WaitHandle. 在讨论这个问题之前,我们先了解 ...

  8. c# AutoResetEvent和ManualResetEvent

    网上有很多AutoResetEvent和ManualResetEvent的详细介绍,在这里不做过多详细的解释,写下自己的一点心得留作备忘. AutoResetEvent和ManualResetEven ...

  9. C# 线程的挂起与唤醒 (AutoResetEvent,ManualResetEvent)

    如果说C#和C++有什么不同,博主不得不说,对于异步的支持程度是C#的一一个伟大的进步. 其实早期的C++都没有异步,并发的概念.博主第一次使用C++创建异步程序的时候,是使用boost库的内容进行实 ...

  10. C# ManualResetEvent

    原文链接 http://dotnetpattern.com/threading-manualresetevent ManualResetEvent 和AutoResetEvent一样,是另外一种.NE ...

最新文章

  1. 【问题帖】压缩图片大小至指定Kb以下
  2. 【Java 泛型】泛型用法 ( 泛型编译期擦除 | 上界通配符 <? extends T> | 下界通配符 <? super T> )
  3. SAP S/4HANA生产排期scheduling profile配置
  4. SharePoint 2013 Farm 安装指南——Least Privilege
  5. 术中导航_密码术中的计数器(CTR)模式
  6. freertos内核 任务定义与切换 原理分析
  7. QT Core | 信号槽03 - 自定义信号与槽
  8. vue echarts动态数据定时刷新
  9. 【OpenCV】角点检测:Harris角点及Shi-Tomasi角点检测
  10. 1.1.2 Greedy Gift Givers 贪婪的送礼者
  11. sql server2008如何修改mac地址_QCC304x/QCC514x:修改蓝牙MAC地址及名称
  12. 222.完全二叉树的节点个数
  13. oracle的多个exclude,记录一下expdp exclude的用法
  14. python做波士顿房价预测
  15. 怎样才能彻底地删除多余输入法软件
  16. HtmlUnit入门教程
  17. Python3 open()函数
  18. tikz包 安装_TikZ: LaTeX绘图包
  19. android多渠道打包
  20. 色温(光源,环境,季节)

热门文章

  1. 威纶和s7200通讯线_S7-200PLC和威纶通触摸屏MODBUS RTU协议通讯实例
  2. android桌面半透明,Android仿Iphone屏幕底部弹出半透明PopupWindow效果
  3. excel常用功能记录(不断更新)
  4. UE4游戏提取的通用步骤(21_9_8)
  5. QCC3040---Application启动流程
  6. 接口测试用例设计方法
  7. 中国省-市-县(区)三级城市数据(json和数组)
  8. HTML+CSS静态页面`西安旅游网站设计——西安旅游(7页) 大学生旅游网页作品 出行网页设计作业模板 学生游玩网页制作源代码下载
  9. 快速对二叉树和前中后序遍历的相互转化
  10. MessageBox的用法