• Thread系列之ManualResetEvent


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

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

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

    代码示例:

    代码
    class Program
    {
    staticvoid 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");
    }
    publicdouble 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的作用,用于通知一个或多个线程某个事件发生。

  • 相关阅读:
    dynamic和匿名对象
    生成1亿个不重复的8位随机整数
    Storage,Memcache,KVDB都是存储服务,如何区分何时用何种服务
    深入理解jQuery中$.get、$.post、$.getJSON和$.ajax的用法
    常用工具
    数字格式化,保留一位小数,无小数用0补充
    学习某些API的方法
    程序员的学习方法(程序员必看)【风中叶老师讲述】
    html的dtd声明
    数据库管理工具navicat基本使用方法——以MySql为例
  • 原文地址:https://www.cnblogs.com/xyqCreator/p/2854454.html
Copyright © 2020-2023  润新知