zoukankan      html  css  js  c++  java
  • Thread系列——ManualResetEvent

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

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

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

    代码示例:

    代码
    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的作用,用于通知一个或多个线程某个事件发生。

  • 相关阅读:
    Razor使用Parse()时最好指定“缓存名”
    脱离MVC使用Razor模板引擎
    ASP.NET内核几大对象、ASP.NET核心知识(6)
    一般处理程序、ASP.NET核心知识(5)
    WebApplication和WebSite的区别
    写一个简易web服务器、ASP.NET核心知识(4)
    JQuery的链式编程,隐式迭代是啥意思?
    JQuery选择器
    JQuery的几个基础操作
    写一个简易浏览器、ASP.NET核心知识(3)
  • 原文地址:https://www.cnblogs.com/ATually/p/1857624.html
Copyright © 2011-2022 走看看