时间:2021-05-20
在多线程开发中,时常用到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 区别的文章就介绍到这了,更多相关C#中ManualResetEvent AutoResetEvent 内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
搞过C#多线程的人对其中的AutoResetEvent和ManualResetEvent这两个类都理解,其中的WaitOne()方法和Set()以及Reset(
最近捣鼓了一下多线程的同步问题,发现其实C#关于多线程同步事件处理还是很灵活,这里主要写一下,自己测试的一些代码,涉及到了AutoResetEvent和Manu
C#多线程与异步的区别详解随着拥有多个硬线程CPU(超线程、双核)的普及,多线程和异步操作等并发程序设计方法也受到了更多的关注和讨论。本文主要是想与各位高手一同
本文实例讲述了C#多线程学习之使用线程池进行多线程的自动管理。分享给大家供大家参考。具体如下:在多线程的程序中,经常会出现两种情况:一种情况:应用程序中,线程把
问题:对于多线程编程,很多时候往往需要向线程中传递多个参数,而C#中的线程只接收1个object类型的参数(如下):Threadt=newThread(newP