前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ManualResetEvent 线程同步「建议收藏」

ManualResetEvent 线程同步「建议收藏」

作者头像
全栈程序员站长
发布2022-09-09 10:29:56
2000
发布2022-09-09 10:29:56
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

ManualResetEvent

ManualResetEvent 用于线程同步,通知一个或多个线程某事件已经发生。通常用于一个线程执行的任务必须在其他线程的任务执行之前完成。

ManualResetEvent状态分为两种:终止状态和非终止状态。当某一任务完成时,将ManualResetEvent设置为终止状态,这样其他等待的线程(一个或多个)将开始执行自己的任务。

注意:一旦它被终止,它将保持终止状态,直到它被手动重置。

代码示例:

代码

代码语言:javascript
复制
     class
     
     
      Program
 { 
      
 
     
     
     static
     
     
      
     
     
     void
     
     
      Main(
     
     
     string
     
     
     [] args)
 { 
      
 Caclultae calc 
     
     
     =
     
     
      
     
     
     new
     
     
      Caclultae();
 Console.WriteLine(
     
     
     "
     
     
     Result={0}
     
     
     "
     
     
     ,calc.result(
     
     
     234
     
     
     ).ToString());
 
 Console.Read();
 }
 }
 
     
     
     class
     
     
      Caclultae
 { 
      
 
     
     
     double
     
     
      baseNum,firNum,secNum,thdNum;
 AutoResetEvent[] autoEvents;
 ManualResetEvent manualEvent;
 Random Generator;
 
     
     
     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[
     
     
     0
     
     
     ].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[
     
     
     1
     
     
     ].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[
     
     
     2
     
     
     ].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 
     
     
     +
     
     
      thdNum;
 }
 
 }

代码中,我们可以看到,CalFirst,CalSec,CalThird都在等待CalBase执行完成。当CalBase计算出BaseNum的结果之后,将ManualResetEvent变量设置为终止状态,通知其他三个任务,可以执行他们自己的任务了。

执行结果:

1).执行一次的结果:

2). 再次执行的结果:

从两次执行结果中看出,CalFirst、CalSec、CalThird的执行顺序是不一定的,也就是说 这三个的地位是相同的,都在等待CalBase执行成功,从而执行自己的任务。这也验证了 ManualResetEvent的作用,用于通知一个或多个线程某个事件发生。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/161182.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ManualResetEvent
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档