C#AutoResetEvent和manualreseteventslim的区别

C#多线程:深入了解线程同步lock,Monitor,Mutex,同步事件和等待句柄(中)...
C#多线程:深入了解线程同步lock,Monitor,Mutex,同步事件和等待句柄(中)...
  本篇继续介绍WaitHandler类及其子类 Mutex,ManualResetEvent,AutoResetEvent的用法。.NET中线程同步的方式多的让人看了眼花缭乱,究竟该怎么去理解呢?其实,我们抛开.NET环境看线程同步,无非是执行两种操作:一是互斥/加锁,目的是保证临界区代码操作的“原子性”;另一种是信号灯操作,目的是保证多个线程按照一定顺序执行,如生产者线程要先于消费者线程执行。.NET中线程同步的类无非是对这两种方式的封装,目的归根结底都可以归结为实现互斥/ 加锁或者是信号灯这两种方式,只是它们的适用场合有所不。下面我们根据类的层次结构了解WaitHandler及其子类。1.WaitHandlerWaitHandle是Mutex,Semaphore,EventWaitHandler,AutoResetEvent,ManualResetEvent共同的祖先,它封装Win32同步句柄内核对象,也就是说是这些内核对象的托管版本。线程可以通过调用WaitHandler实例的方法WaitOne在单个等待句柄上阻止。此外,WaitHandler类重载了静态方法,以等待所有指定的等待句柄都已收集到信号WaitAll,或者等待某一指定的等待句柄收集到信号WaitAny。这些方法都提供了放弃等待的超时间隔、在进入等待之前退出同步上下文的机会,并允许其它线程使用同步上下文。WaitHandler是C#中的抽象类,不能实例化。2.EventWaitHandler vs. ManualResetEvent vs. AutoResetEvent(同步事件)我们先看看两个子类ManualResetEvent和AutoResetEvent在.NET Framework中的实现:C#代码  //.NET&Framework中ManualResetEvent类的实现[ComVisible(true),&HostProtection(SecurityAction.LinkDemand,&Synchronization&=&true,&ExternalThreading&=&true)]public&sealed&class&ManualResetEvent&:&EventWaitHandle{//&Methodspublic&ManualResetEvent(bool&initialState)&:&base(initialState,&EventResetMode.ManualReset){}}//.NET&Framework中AutoResetEvent类的实现[ComVisible(true),&HostProtection(SecurityAction.LinkDemand,&Synchronization&=&true,&ExternalThreading&=&true)]public&sealed&class&AutoResetEvent&:&EventWaitHandle{//&Methodspublic&AutoResetEvent(bool&initialState):&base(initialState,&EventResetMode.AutoReset){}}原来ManualResetEvent和AutoResetEvent都继承自EventWaitHandler,它们的唯一区别就在于父类 EventWaitHandler的构造函数参数EventResetMode不同,这样我们只要弄清了参数EventResetMode值不同时,EventWaitHandler类控制线程同步的行为有什么不同,两个子类也就清楚了。为了便于描述,我们不去介绍父类的两种模式,而直接介绍子类。ManualResetEvent和AutoResetEvent的共同点:1)Set方法将事件状态设置为终止状态,允许一个或多个等待线程继续;Reset方法将事件状态设置为非终止状态,导致线程阻止;WaitOne阻止当前线程,直到当前线程的WaitHandler收到事件信号。2)可以通过构造函数的参数值来决定其初始状态,若为true则事件为终止状态从而使线程为非阻塞状态,为false则线程为阻塞状态。3)如果某个线程调用WaitOne方法,则当事件状态为终止状态时,该线程会得到信号,继续向下执行。ManualResetEvent和AutoResetEvent的不同点:1)AutoResetEvent.WaitOne()每次只允许一个线程进入,当某个线程得到信号后,AutoResetEvent会自动又将信号置为不发送状态,则其他调用WaitOne的线程只有继续等待,也就是说AutoResetEvent一次只唤醒一个线程;2)ManualResetEvent则可以唤醒多个线程,因为当某个线程调用了ManualResetEvent.Set()方法后,其他调用WaitOne的线程获得信号得以继续执行,而ManualResetEvent不会自动将信号置为不发送。3)也就是说,除非手工调用了ManualResetEvent.Reset()方法,则ManualResetEvent将一直保持有信号状态,ManualResetEvent也就可以同时唤醒多个线程继续执行。示例场景:张三、李四两个好朋友去餐馆吃饭,两个人点了一份宫爆鸡丁,宫爆鸡丁做好需要一段时间,张三、李四不愿傻等,都专心致志的玩起了手机游戏,心想宫爆鸡丁做好了,服务员肯定会叫我们的。服务员上菜之后,张三李四开始享用美味的饭菜,饭菜吃光了,他们再叫服务员过来买单。我们可以从这个场景中抽象出来三个线程,张三线程、李四线程和服务员线程,他们之间需要同步:服务员上菜—&张三、李四开始享用宫爆鸡丁—&吃好后叫服务员过来买单。这个同步用什么呢? ManualResetEvent还是AutoResetEvent?通过上面的分析不难看出,我们应该用ManualResetEvent进行同步,下面是程序代码:张三李四吃饭的故事C#代码  &public&class&EventWaitTest{private&string&&//顾客姓名//private&static&AutoResetEvent&eventWait&=&new&AutoResetEvent(false);private&static&ManualResetEvent&eventWait&=&new&ManualResetEvent(false);private&static&ManualResetEvent&eventOver&=&new&ManualResetEvent(false);public&EventWaitTest(string&name){this.name&=&}public&static&void&Product(){Console.WriteLine("服务员:厨师在做菜呢,两位稍等");Thread.Sleep(2000);Console.WriteLine("服务员:宫爆鸡丁好了");eventWait.Set();while&(true){if&(eventOver.WaitOne(1000,&false)){Console.WriteLine("服务员:两位请买单");eventOver.Reset();}}}public&void&Consume(){while&(true){if&(eventWait.WaitOne(1000,&false)){Console.WriteLine(this.name&+&":开始吃宫爆鸡丁");Thread.Sleep(2000);Console.WriteLine(this.name&+&":宫爆鸡丁吃光了");eventWait.Reset();eventOver.Set();}else{Console.WriteLine(this.name&+&":等着上菜无聊先玩会手机游戏");}}}}public&class&App{public&static&void&Main(string[]&args){EventWaitTest&zhangsan&=&new&EventWaitTest("张三");EventWaitTest&lisi&=&new&EventWaitTest("李四");Thread&t1&=&new&Thread(new&ThreadStart(zhangsan.Consume));Thread&t2&=&new&Thread(new&ThreadStart(lisi.Consume));Thread&t3&=&new&Thread(new&ThreadStart(EventWaitTest.Product));t1.Start();t2.Start();t3.Start();Console.Read();}}编译后查看运行结果,符合我们的预期,控制台输出为:服务员:厨师在做菜呢,两位稍等...张三:等着上菜无聊先玩会手机游戏李四:等着上菜无聊先玩会手机游戏张三:等着上菜无聊先玩会手机游戏李四:等着上菜无聊先玩会手机游戏服务员:宫爆鸡丁好了张三:开始吃宫爆鸡丁李四:开始吃宫爆鸡丁张三:宫爆鸡丁吃光了李四:宫爆鸡丁吃光了服务员:两位请买单如果改用AutoResetEvent进行同步呢?会出现什么样的结果?恐怕张三和李四就要打起来了,一个享用了美味的宫爆鸡丁,另一个到要付账的时候却还在玩游戏。感兴趣的朋友可以把注释的那行代码注释去掉,并把下面一行代码注释掉,运行程序看会出现怎样的结果。3.Mutex(互斥体)Mutex和EventWaitHandler有着共同的父类WaitHandler类,它们同步的函数用法也差不多,这里不再赘述。Mutex的突出特点是可以跨应用程序域边界对资源进行独占访问,即可以用于同步不同进程中的线程,这种功能当然这是以牺牲更多的系统资源为代价的。这种跨进程同步的一种应用是,限制同一台电脑中同时打开两个相同的程序。具体实现可以参考《用Mutex或进程限制用户在一台电脑上同时打开两个程序》。
24小时热点ManualResetEvent和AutoResetEvent的区别
在讨论这个问题之前,我们先了解这样一种观点,线程之间的通信是通过发信号来进行沟通的。(这不是废话)
&&&&& 先来讨论ManualResetEvent,讨论过程中我会穿插一些AutoResetEvent的内容,来做对比:
&&&&&&ManualResetEvent都可以阻塞一个或多个线程,直到收到一个信号告诉ManualResetEvent不要再阻塞当前的线程。
可以想象ManualResetEvent这个对象内部有一个Boolean类型的属性IsRelease来控制是否要阻塞当前线程。这个属性我们在初始化的时候可以设置它,如ManualResetEvent event=new ManualResetEvent(false);这就表明默认的属性是要阻塞当前线程。
&&&&& 代码举例:
&&&&&&& ManualResetEvent _manualResetEvent = new ManualResetEvent(false);
&&&&&&& private void BT_Temp_Click(object sender, RoutedEventArgs e)
&&&&&&&&&&& Thread t1 = new Thread(this.Thread1Foo);
&&&&&&&&&&& t1.Start();&//启动线程1
&&&&&&&&&&& Thread t2 = new Thread(this.Thread2Foo);
&&&&&&&&&&& t2.Start();&//启动线程2
&&&&&&&&&&& Thread.Sleep(3000);&//睡眠当前主线程,即调用BT_Temp_Click的线程
&&&&&&&&&&& _manualResetEvent .Set();&& //想象成将IsRelease设为True&
&&&&&&& void Thread1Foo()
&&&&&&&&&&& _manualResetEvent .WaitOne();&
//阻塞线程1,直到主线程发信号给线程1,告知_menuResetEvent你的IsRelease属性已经为true,
//这时不再阻塞线程1,程序继续往下跑
&&&&&&&&&&& MessageBox.Show(&t1 end&);
&&&&&&& void Thread2Foo()
&&&&&&&&&&& _manualResetEvent .WaitOne();
//阻塞线程2,直到主线程发信号给线程1,告知_menuResetEvent你的IsRelease属性已经为true,
//这时不再阻塞线程2,程序继续往下跑
&&&&&&&&&&& MessageBox.Show(&t2 end&);
&&&&&& 注意这里ManualResetEvent和AutoResetEvent的一个重要区别:
&&&&&& manual的话肯定会给线程1和线程2都发送一个信号,而auto只会随机给其中一个发送信号。
&&&&&& 为什么一个叫manual而一个叫auto呢?我想这是很多人的疑问,现在我们就来看这个问题。
&&&&&& 刚才_manualResetEvent .Set();的这句话我想大家都明白了,可以看做将IsRelease的属性设置为true.线程1中
&_manualResetEvent.WaitOne();接收到信号后不再阻塞线程1。在此之后的整个过程中IsRelease的值都是true.如果
想将IsRelease的值回复成false,就必须再调用_manualResetEvent.Reset()的方法。
&&&&&& 如果是_autoResetEvent.set(),那么_autoResetEvent.WaitOne()后会自动将IsRelease的值自动设置为false.
这就是为什么一个叫auto,一个叫manual.&&&&
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'Thread系列之ManualResetEvent_C# 博文_CS程序员之窗
热门搜索: ,
您的位置:
&&&&&&&&&&&Thread系列之ManualResetEvent
Thread系列之ManualResetEvent
来自:博客园&
字体大小:【&&】
摘要:ManualResetEvent 用于线程同步,通知一个或多个线程某事件已经发生。通常用于一个线程执行的任务必须在其他线程的任务执行之前完成。
ManualResetEvent 用于线程同步,通知一个或多个线程某事件已经发生。通常用于一个线程执行的任务必须在其他线程的任务执行之前完成。
ManualResetEvent状态分为两种:终止状态和非终止状态。当某一任务完成时,将ManualResetEvent设置为终止状态,这样其他等待的线程(一个或多个)将开始执行自己的任务。
注意:一旦它被终止,它将保持终止状态,直到它被手动重置。
代码示例:
class Program
static void Main(string[] args)
Caclultae calc = new Caclultae();
Console.WriteLine(&Result={0}&,calc.result(<span style="color: #4).ToString());
Console.Read();
class Caclultae
double baseNum,firNum,secNum,thdN
AutoResetEvent[] autoE
ManualResetEvent manualE
public Caclultae()
autoEvents = new AutoResetEvent[]
new AutoResetEvent(false),
new AutoResetEvent(false),
new AutoResetEvent(false)
manualEvent = new ManualResetEvent(false);
void CalBase(object stateInfo)
baseNum = Generator.NextDouble();
Console.WriteLine(&BaseNum is Ok&);
manualEvent.Set();
void CalFirst(object stateInfo)
double preCalc = Generator.NextDouble();
manualEvent.WaitOne();
Console.WriteLine(&FirstNum begins to Calculate&);
firNum = preCalc * baseNum * Generator.NextDouble();
autoEvents[<span style="color: #].Set();
Console.WriteLine(&FirstNum Calculates successfully&);
void CalSec(object stateInfo)
double preCalc = Generator.NextDouble();
manualEvent.WaitOne();
Console.WriteLine(&SecNum begins to Calculate&);
secNum = preCalc * baseNum * Generator.NextDouble();
autoEvents[<span style="color: #].Set();
Console.WriteLine(&SecNum
Calculates successfully&);
void CalThird(object stateInfo)
double preCalc = Generator.NextDouble();
manualEvent.WaitOne();
Console.WriteLine(&ThrdNum begins to Calculate&);
thdNum = preCalc * baseNum * Generator.NextDouble();
autoEvents[<span style="color: #].Set();
Console.WriteLine(&ThrdNum
Calculates successfully&);
public double result(int seed)
Generator = new Random(seed);
ThreadPool.QueueUserWorkItem(new WaitCallback(CalBase));
ThreadPool.QueueUserWorkItem(new WaitCallback(CalFirst));
ThreadPool.QueueUserWorkItem(new WaitCallback(CalSec));
ThreadPool.QueueUserWorkItem(new WaitCallback(CalThird));
WaitHandle.WaitAll(autoEvents);
manualEvent.Reset();
return firNum + secNum + thdN
代码中,我们可以看到,CalFirst,CalSec,CalThird都在等待CalBase执行完成。当CalBase计算出BaseNum的结果之后,将ManualResetEvent变量设置为终止状态,通知其他三个任务,可以执行他们自己的任务了。
执行结果:
1).执行一次的结果:
2). 再次执行的结果:
从两次执行结果中看出,CalFirst、CalSec、CalThird的执行顺序是不一定的,也就是说 这三个的地位是相同的,都在等待CalBase执行成功,从而执行自己的任务。这也验证了 ManualResetEvent的作用,用于通知一个或多个线程某个事件发生。
作者:m苗子
上一篇:&&&&&&下一篇:
相关文章:
该文章已有条评论
作品版权作者所有,如果无意之中侵犯了你的版权请来信告知,本站将在3个工作日内删除。
CopyRight@
All rights reserved
&&&&苏ICP备号
客户服务信箱:starts_C#技巧(25)
& & & & 在.Net多线程编程中,AutoResetEvent和ManualResetEvent这两个类经常用到, 他们的用法很类&#20284;,但也有区别。Set方法将信号置为发送状态,Reset方法将信号置为不发送状态,WaitOne等待信号的发送。可以通过构造函数的参数&#20540;来决定其初始状态,若为true则非阻塞状态,为false为阻塞状态。如果某个线程调用WaitOne方法,则当信号处于发送状态时,该线程会得到信号,
继续向下执行。其区别就在调用后,AutoResetEvent.WaitOne()每次只允许一个线程进入,当某个线程得到信号后,AutoResetEvent会自动又将信号置为不发送状态,则其他调用WaitOne的线程只有继续等待.也就是说,AutoResetEvent一次只唤醒一个线程;而ManualResetEvent则可以唤醒多个线程,因为当某个线程调用了ManualResetEvent.Set()方法后,其他调用WaitOne的线程获得信号得以继续执行,而ManualResetEvent不会自动将信号置为不发送。也就是说,除非手工调用了ManualResetEvent.Reset()方法,则ManualResetEvent将一直保持有信号状态,ManualResetEvent也就可以同时唤醒多个线程继续执行。AutoResetEvent在WaitOne()时,自动调用Reset将信号量复位;而ManualResetEvent则需要手动调用Reset方法将信号量复位。
&ManualResetEvent
&&&&&&“ManualResetEvent 类表示一个本地等待处理事件,在已发事件信号后必须手动重置该事件。”“在调用
ManualResetEvent 对象的 Reset 方法之前,该对象始终保持已发信号状态。在对象保持已发信号状态期间,可以释放任意数目的等待线程或在已发事件信号后仍等待事件的线程。”
AutoResetEvent
&&&&&& &“AutoResetEvent 类表示一个本地等待处理事件,在释放了单个等待线程以后,该事件会在终止时自动重置。”“在释放了单个等待线程以后,系统会自动将一个
AutoResetEvent 对象重置为非终止。如果没有线程在等待,事件对象的状态会保持为终止。”
ManualResetEvent类、AutoResetEvent类&
& & & & 这两个类都是由EventWaitHandle类派生出来的,所以功能和调用方法都很相&#20284;。&这两个类常用于阻断某个线程的执行,然后在符合条件的情况下再恢复其执行。&举个例子,你想送花给一个MM,托了一个送花的小伙子送了过去,而你希望当MM收到花之后就立即打个电话过去告诉她。&但问题是你不知道花什么时候才送到MM的手里,打早了打迟了都不好,这时你可以使用ManualResetEvent对象帮忙。当委&托小伙子送花过去的时候,使用ManualResetEvent的WaitOne方法进行等待。当小伙子把花送到MM的手中时,再调用一下&ManualResetEvent的Set方法,你就可以准时地打电话过去了。&另外ManualResetEvent还有一个Reset方法,用来重新阻断调用者执行的,情况就好比你委托了这个小伙子送花给N个MM,而又想准时地给这N个MM打电话的情况一样。&
class Program
private static ManualResetEvent ent = new ManualResetEvent(false);
public static void Main()
Boy sender = new Boy(ent);
for (int i = 0; i & 3; i++)
Thread th = new Thread(() =& sender.SendFlower(i));
th.Start();
ent.Reset();
ent.WaitOne(); //等待工作
Console.WriteLine(&收到了吧,花是我送嘀:)&);
Console.ReadLine();
public class Boy
ManualResetE
public Boy(ManualResetEvent e)
public void SendFlower(int mmIndex)
Console.WriteLine();
Console.WriteLine(&正在送花给MM& + mmIndex + &的途中&);
for (int i = 0; i & 10; i++)
Thread.Sleep(200);
Console.Write(&..&);
Console.WriteLine();
Console.WriteLine(&花已经送到MM& + mmIndex + &手中了,boss&);
ent.Set();
& & & & 而AutoResetEvent类故名思意,就是在每次Set完之后自动Reset。让执行程序重新进入阻塞状态。&即AutoResetEvent.Set()
相当于 ManualResetEvent.Set() 之后又立即 ManualResetEvent.Reset(),&其他的就没有什么不同的了。&举个送花给N个MM的例子:&
public class TestMain
private static AutoResetEvent ent = new AutoResetEvent(false);
public static void Main()
Boy sender = new Boy(ent);
for (int i = 0; i & 3; i++)
Thread th = new Thread(() =& sender.SendFlower(i));
th.Start();
ent.WaitOne(); //等待工作
Console.WriteLine(&收到了吧,花是我送嘀:)&);
Console.ReadLine();
public class Boy
AutoResetE
public Boy(AutoResetEvent e)
public void SendFlower(int mmIndex)
Console.WriteLine();
Console.WriteLine(&正在送花给MM&+mmIndex+&的途中&);
for (int i = 0; i & 10; i++)
Thread.Sleep(200);
Console.Write(&..&);
Console.WriteLine();
Console.WriteLine(&花已经送到MM& + mmIndex + &手中了,boss&);
ent.Set(); //通知阻塞程序,这里的效果相当于 ManualResetEvent的Set()方法+Reset()方法
} & & & &&要注意的是ManualResetEvent和AutoResetEvent 的构造函数都有一个bool的参数,用这个参数可以指定初始情况下,同步对象的处于阻塞(设置为false)还是非阻塞(设置为true)的状态。&
另外WaitOne方法也可以带两个参数:&
WaitOne (int millisecondsTimeout,bool exitContext)&
millisecondsTimeout:等待的毫秒数,或为 Timeout.Infinite (-1),表示无限期等待。&
exitContext:为 true,则等待之前先退出上下文的同步域(如果在同步上下文中),然后在稍后重新获取它;否则为false。&
& & & & &就是说,等待是可以加上一个期限的,如果等待的同步对象一直都不Set()的话,那么程序就会卡死,所以在WaitOne方法里面可以放置一个时间期限,单位是毫秒。
Mutex混合了 AutoResetEvent与ManualResetEvent的一些特性,简单来说:
1.Mutex和AutoResetEvent一样,只能允许一个线程进入。当一个线程获得许可之后,其它等待的线程必须继续等待;
2.Mutex和ManualResetEvent一样,必须手动释放许可证,即调用Mutex.ReleaseMutex()方法。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:103527次
积分:1305
积分:1305
排名:千里之外
原创:25篇
转载:40篇
评论:13条
(1)(1)(6)(13)(2)(1)(3)(2)(2)(2)(3)(3)(2)(3)(2)(2)(8)(2)(1)(2)(1)(3)(1)C#深入理解AutoResetEvent和ManualResetEvent - 推酷
C#深入理解AutoResetEvent和ManualResetEvent
当在C#使用多线程时就免不了使用AutoResetEvent和ManualResetEvent类,可以理解这两个类可以通过设置信号来让线程停下来或让线程重新启动,其实与操作系统里的信号量很相似(汗,考完考试已经有点忘记了)。下面上代码
class Program
const int count = 10;
//赋值为false也就是没有信号
static AutoResetEvent myResetEvent = new AutoResetEvent(false);
static void Main(string[] args)
Thread thread = new Thread(funThread);
thread.Name = "QQ";
thread.Start();
for (int i = 1; i & i++)
Console.WriteLine("first number: {0}",i);
//这里是设置为有信号
myResetEvent.Set();
Thread.Sleep(2000);
thread.Abort();
static void funThread()
while (true)
//执行到这个地方时,会等待set调用后改变了信号才接着执行
myResetEvent.WaitOne();
Console.WriteLine("end {0} number: {1}", Thread.CurrentThread.Name, number);
输出结果为
first number:1
end QQ number:1
first number:2
end QQ number:3
简单来说只有调用Set()方法后才能执行WaitOne()后面的代码,AutoResetEvent和ManualResetEvent分别都有Set()改变为有信号 ,Reset()改变为无信号,WaitOne()将会阻塞当前调用的线程,直到有信号为止,即执行了Set()方法,WaitOne()方法还可以带指定时间的参数。
理解了AutoResetEvent后再理解ManualResetEvent也就不难了,AutoResetEvent与ManualResetEvent的区别是,AutoResetEvent.WaitOne()会自动改变事件对象的状态,即AutoResetEvent.WaitOne()每执行一次,事件的状态就改变一次,也就是从无信号变为有信号,或从有信号变为无信号。而ManualResetEvent则是调用Set()方法后其信号量不会自动改变,除非再设置Reset()方法。
在.Net多线程编程中,AutoResetEvent和ManualResetEvent这两个类经常用到, 他们的用法很类似,但也有区别。Set方法将信号置为发送状态,Reset方法将信号置为不发送状态,WaitOne等待信号的发送。可以通过构造函数的参数值来决定其初始状态,若为true则非阻塞状态,为false为阻塞状态。如果某个线程调用WaitOne方法,则当信号处于发送状态时,该线程会得到信号, 继续向下执行。其区别就在调用后,AutoResetEvent.WaitOne()每次只允许一个线程进入,当某个线程得到信号后,AutoResetEvent会自动又将信号置为不发送状态,则其他调用WaitOne的线程只有继续等待.也就是说,AutoResetEvent一次只唤醒一个线程;而ManualResetEvent则可以唤醒多个线程,因为当某个线程调用了ManualResetEvent.Set()方法后,其他调用WaitOne的线程获得信号得以继续执行,而ManualResetEvent不会自动将信号置为不发送。也就是说,除非手工调用了ManualResetEvent.Reset()方法,则ManualResetEvent将一直保持有信号状态,ManualResetEvent也就可以同时唤醒多个线程继续执行。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致

我要回帖

更多关于 autoresetevent count 的文章

 

随机推荐