还在纠结manualresetevent?看完这篇你就懂了!

吉云

今儿个,咱来聊聊ManualResetEvent这个玩意儿,这东西在多线程编程里头可有点儿用,能帮咱控制线程啥时候跑、啥时候歇着。说白,就是个信号灯。

我也不咋明白这玩意儿到底咋使,就去网上搜搜,看些资料。还真有点儿绕,不过琢磨琢磨,也就那么回事儿。

摸索过程

还在纠结manualresetevent?看完这篇你就懂了!

我一开始是想实现这么一个功能:让一个线程先跑着,跑到一半儿,让它停下来,等另一个线程干完活儿,再让这个线程继续跑。这不就是线程之间的协作嘛

我直接上代码,想看看这ManualResetEvent到底咋回事。我先是这样写的:


ManualResetEvent mre = new ManualResetEvent(false);

还在纠结manualresetevent?看完这篇你就懂了!

这句代码的意思,就是创建一个ManualResetEvent对象,名字叫mre,然后给它一个初始状态,false。这false啥意思?就是说,这个信号灯是红灯,不让过。

然后,我写两个线程,一个线程里头,我让它先跑一段儿,然后调用*(),意思就是让这个线程在这儿等着,等绿灯亮再走。

另一个线程里头,我干点儿别的活儿,干完,调用*(),意思就是把信号灯变成绿灯,让等着的那哥们儿可以走。

我这么一跑,还真行!第一个线程跑到一半儿,停下来,等第二个线程干完活儿,它又继续跑。

实践出真知

还在纠结manualresetevent?看完这篇你就懂了!

光看不练假把式,我得动手试试。我写个小例子,模拟两个线程下载文件。一个线程负责下载文件头,另一个线程负责下载文件体。我想让下载文件头的线程先跑,下载完文件头,然后停下来,等下载文件体的线程下载完文件体,再把它们合并起来。

代码大概是这样的:


// 创建ManualResetEvent对象,初始状态为false,表示红灯

ManualResetEvent mre = new ManualResetEvent(false);

还在纠结manualresetevent?看完这篇你就懂了!

// 下载文件头的线程

Thread thread1 = new Thread(() =>

*("开始下载文件头...");

// 模拟下载文件头

*(2000);

还在纠结manualresetevent?看完这篇你就懂了!

*("文件头下载完成!");

// 等待信号,绿灯亮才能继续

*("开始合并文件...");

// 模拟合并文件

*(1000);

还在纠结manualresetevent?看完这篇你就懂了!

*("文件合并完成!");

// 下载文件体的线程

Thread thread2 = new Thread(() =>

*("开始下载文件体...");

还在纠结manualresetevent?看完这篇你就懂了!

// 模拟下载文件体

*(3000);

*("文件体下载完成!");

// 发送信号,把红灯变绿灯

还在纠结manualresetevent?看完这篇你就懂了!

// 启动线程

我跑一下这个例子,结果跟我预期的一样:

还在纠结manualresetevent?看完这篇你就懂了!

  • 先打印“开始下载文件头...”。
  • 然后等2秒,打印“文件头下载完成!”。
  • 它就停在那儿,等着。
  • 再过3秒,打印“开始下载文件体...”和“文件体下载完成!”。
  • 打印“开始合并文件...”和“文件合并完成!”。
  • 还在纠结manualresetevent?看完这篇你就懂了!

一点小总结

通过这回实践,我对ManualResetEvent的理解更深。这玩意儿就像一个开关,或者说一个信号灯。new ManualResetEvent(false)就是创建一个红灯,就是让线程在这儿等着,直到等到绿灯,就是把红灯变绿灯,让之前等待的线程继续。如果一开始是new ManualResetEvent(true),那就是绿灯,线程一来就能直接过,不用等。

而且这ManualResetEvent,跟AutoResetEvent还不太一样。ManualResetEvent,你Set()一次,所有等着WaitOne()的线程都能收到信号继续走。但是必须手动调用Reset()重置信号量状态为非终止。而AutoResetEvent,你Set()一次,就只有一个线程能收到,然后它就自动把灯变回红色。这个得根据实际情况来选择用哪个。

这ManualResetEvent还是挺有用的,以后在多线程编程的时候,又多一个工具可以用!

免责声明:由于无法甄别是否为投稿用户创作以及文章的准确性,本站尊重并保护知识产权,根据《信息网络传播权保护条例》,如我们转载的作品侵犯了您的权利,请您通知我们,请将本侵权页面网址发送邮件到qingge@88.com,深感抱歉,我们会做删除处理。

目录[+]