线程是程序中的控制流程的封装。你可能已经习惯于写单线程程序,也就是,程序在它们的代码中一次只在一条路中执行。如果你多弄几个线程的话,代码运行可能会更加“同步”。在一个有着多线程的典型进程中,零个或更多线程在同时运行。但是,在有着N个CPU的机器上,一个线程只能在给定的时间上在一个CPU上运行,因为每个线程都是一个代码段,每个CPU一次只能运行一段代码。而看起来像是N个同时完成是线程间共享CPU时间片的效果。这个例子里,我们将创建另一个线程,我们将用两个线程演示多线程的工作方式,最后,我们实现两个线程(主线程与新线程)同步,在新线程工作前必须等待消息。建立线程前我们必须引入System.Threading命名空间。然后我需要知道的是,线程得为控制流程建立一个起点。起点是一个函数,可以使一个相同的调用或其它。
这里你可以看到在同一个类中定义的起点函数。
using System;
using System.Threading;
namespace ThreadingTester
{
    class ThreadClass
    {
        public static void trmain()
        {
            for (int x = 0; x < 10; x++)
            {
                Thread.Sleep(1000);
                Console.WriteLine(x);
            }
        }
        static void Main(string[] args)
        {
            Thread thrd1 = new Thread(new ThreadStart(trmain));
            thrd1.Start();
            for (int x = 0; x < 10; x++)
            {
                Thread.Sleep(900);
                Console.WriteLine("Main    :" + x);
            }
        }
    }
}
Thread.Sleep(n)方法把“this”线程置于n毫秒的休眠状态。你可以看看这个例子,在主函数我们定义了一个新的线程,其中它的起点是函数trmain(),我们然后包含了Start()方法开始执行。如果你运行这个例子,你就会了解线程间的切换(让CPU从运行一个线程转到另一个线程)让线程几乎同时运行,为了能看哪个线程运行更快我把主线程设置比新线程少100毫秒。
现在,在开始线程前,先给线程命名:
  Thread thrd1=new Thread(new ThreadStart(trmain));
  thrd1.Name="thread1";
  thrd1.Start();
  Thread tr = Thread.CurrentThread;
  Console.WriteLine(tr.Name);
在完成上面程序后,设想我们不想在一开始新线程就让它马上运行结束,也就是说,我们开启了一个新线程,让它运行,在某个特定的时间点,新线程暂停并等待从主线程(或其他线程)发来的消息。
我们可以这样定义:
  public static ManualResetEvent mre = new ManualResetEvent(false);
ManualResetEvent建立时是把false作为start的初始状态,这个类用于通知另一个线程,让它等待一个或多个线程。注意,为了通知或监听同一个线程,所有的其它线程都能访问那个类。
等待线程这样写:
  mre.WaitOne();
这将引起等待线程无限期的阻塞并等待类来通知。
发信号的线程应该这样:
  mre.Set();
这样类就会被通知,值变成true,等待线程就会停止等待。在通知事件发生后,我们就可以使用下面语句把线程置于基状态:
  mre.Reset();
现在让我们在程序执行一下:
using System;
using System.Threading;
namespace ThreadingTester
{
    class ThreadClass
    {
        public static ManualResetEvent mre = new ManualResetEvent(false);
        public static void trmain()
        {
            Thread tr = Thread.CurrentThread;
            Console.WriteLine("thread: waiting for an event");
            mre.WaitOne();
            Console.WriteLine("thread: got an event");
            for (int x = 0; x < 10; x++)
            {
                Thread.Sleep(1000);
                Console.WriteLine(tr.Name + ": " + x);
            }
        }
        static void Main(string[] args)
        {
            Thread thrd1 = new Thread(new ThreadStart(trmain));
            thrd1.Name = "thread1";
            thrd1.Start();
            for (int x = 0; x < 10; x++)
            {
                Thread.Sleep(900);
                Console.WriteLine("Main:" + x);
                if (5 == x) mre.Set();
            }
            while (thrd1.IsAlive)
            {
                Thread.Sleep(1000);
                Console.WriteLine("Main: waiting for thread to stop");
            }
            Console.ReadLine();
        }
    }
}
 
 
 
 
 
另外一个例子:

class Program
    {
        static void Main(string[] args)
        {
            const int taskNum = 10;
            FBNQC[] fbnqc = new FBNQC[taskNum];
            ManualResetEvent[] overEvents = new ManualResetEvent[taskNum];
            Random fbnqP = new Random();
            for (int i = 0; i < taskNum; i++)
            {
                overEvents[i] = new ManualResetEvent(false);
                fbnqc[i] = new FBNQC(fbnqP.Next(20, 40), overEvents[i]);
                ThreadPool.QueueUserWorkItem(fbnqc[i].CallBack , i);
            }
            WaitHandle.WaitAll(overEvents);
            for (int i = 0; i < taskNum; i++)
            {
                Console.WriteLine("Thread{0}'s parameter is {1},result is {2}!", i, fbnqc[i].pFBNQP, fbnqc[i].pFBNQR);
            }
            Console.ReadLine();

}
    }

class FBNQC
    {
        public int pFBNQP { get { return mFBNQP; } }
        public int pFBNQR { get { return mFBNQR; } }
        private int mFBNQP;
        private int mFBNQR;
        ManualResetEvent mOverEvents;
        public FBNQC (int oFBNQP,ManualResetEvent oOverEvents)
        {
            mFBNQP =oFBNQP ;
            mOverEvents =oOverEvents ;
        }

public int  CalculateFBNQ (int oInt)
        {
            if (oInt <= 1) return oInt;
            return CalculateFBNQ(oInt - 1) + CalculateFBNQ(oInt- 2);
        }

public void CallBack(object oObj)
        {
            int threadIndex=(int)oObj ;
            Console .WriteLine ("Thead{0} started....",threadIndex );
            mFBNQR = CalculateFBNQ(mFBNQP);
            Console.WriteLine("Thread{0} has finished!", threadIndex);
            mOverEvents.Set();
        }

注:

由于每个斐波纳契对象是给予一个半随机的值来进行计算,而且因为十个线程中的每一个线程将竞争处理机时间,没有办法提前知道要花多少时间才能计算出所有十个结果。那就是为什么在构造期间每个斐波纳契对象被传递一个ManualResetEvent类的实例。每个对象在完成计算之后发信号给提供了的事件对象,该事件对象允许主线程用WaitAll阻塞执行直到所有十个斐波纳契对象都计算完成,Main 方法接显示每个斐波纳契的结果。

理解多线程中的ManualResetEvent(C#)的更多相关文章

  1. python多线程中join()的理解

    在 Python 的多线程编程中,经常碰到 thread.join()这样的代码.那么今天咱们用实际代码来解释一下 join 函数的作用. 第一,当一个进程启动之后,会默认产生一个主线程,因为线程是程 ...

  2. 深入理解JDK中的I/O

    深入理解JDK中的I/O 目 录 java内存模型GCHTTP协议事务隔离级并发多线程设计模式清楚redis.memcache并且知道区别mysql分表分库有接口幂等性了解jdk8稍微了解一下特性 j ...

  3. 深入理解java中的synchronized关键字

    synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D ...

  4. [译]线程生命周期-理解Java中的线程状态

    线程生命周期-理解Java中的线程状态 在多线程编程环境下,理解线程生命周期和线程状态非常重要. 在上一篇教程中,我们已经学习了如何创建java线程:实现Runnable接口或者成为Thread的子类 ...

  5. c#语言-多线程中的锁系统(一)

    介绍 平常在多线程开发中,总避免不了线程同步.本篇就对net多线程中的锁系统做个简单描述.   目录 一:lock.Monitor        1:基础.        2: 作用域.       ...

  6. Java多线程中线程间的通信

    一.使用while方式来实现线程之间的通信 package com.ietree.multithread.sync; import java.util.ArrayList; import java.u ...

  7. 深入理解Java中的不可变对象

    深入理解Java中的不可变对象 不可变对象想必大部分朋友都不陌生,大家在平时写代码的过程中100%会使用到不可变对象,比如最常见的String对象.包装器对象等,那么到底为何Java语言要这么设计,真 ...

  8. Java Volatile关键字 以及long,double在多线程中的应用

    概念: volatile关键字,官方解释:volatile可以保证可见性.顺序性.一致性. 可见性:volatile修饰的对象在加载时会告知JVM,对象在CPU的缓存上对多个线程是同时可见的. 顺序性 ...

  9. 深入理解Java中的同步静态方法和synchronized(class)代码块的类锁

    一.回顾学习内容 在前面几篇博客中我我们已经理解了synchronized对象锁.对象锁的重入.synchronized方法块.synchronized非本对象的代码块, 链接:https://www ...

随机推荐

  1. 进程间通信(IPC)介绍(转)

    进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息. IPC的方式通常有管道(包括无名管道和命名管道).消息队列.信号量.共享存储.Socket ...

  2. shell脚本学习笔记 (正則表達式)

    正則表達式一般有三个部分组成,他们各自是:字符类,数量限定符,位置限定符. 规定一些特殊语法表示字符类.数 量限定符和位置关系,然后用这些特殊语法和普通字符一起表示一个模式,这就是正則表達式(Regu ...

  3. iOS 自己定义页面的切换动画与交互动画 By Swift

    在iOS7之前,开发人员为了寻求自己定义Navigation Controller的Push/Pop动画,仅仅能受限于子类化一个UINavigationController,或是用自己定义的动画去覆盖 ...

  4. Android加载网络图片学习过程

    好多应用,像我们公司的<乘友>还有其他的<飞鸽><陌陌><啪啪>这些,几乎每一款应用都需要加载网络图片,那ToYueXinShangWan,这是比须熟练 ...

  5. Allegro skill

    https://blog.csdn.net/wyu0725/article/details/52367199 Allegro skill二次开发和更改菜单页面 简单的使用skill;能够使Aleggr ...

  6. js错误: Unexpected number in JSON at position 2792 value里面有双引号怎么解决

    源头  出现这个报错提示,大家从错误就可以看的出来,这就是json的错误,一般来说都是json格式出现了错误,本人遇到比较多的情况就是json字符串里面出现了一些会影响json格式的符号,这次出现这个 ...

  7. python之prettytable

    sdata={'语文':89,'数学':96,'音乐':39,'英语':78,'化学':88} #字典向Series转化 >>> studata=Series(sdata) > ...

  8. 四、Silverlight中使用MVVM(四)——演练

    本来打算用MVVM实现CRUD操作的,这方面例子网上资源还挺多的,毕竟CRUD算是基本功了,因为最近已经开始学习Cailburn框架了,感觉时间 挺紧的,这篇就实现其中的更新操作吧. 功能很明确,当我 ...

  9. Hive总结(四)hive安装记录

    本篇为安装篇较简单: 前提: 1: 安装了hadoop-1.0.4(1.0.3也能够)正常执行 2:安装了hbase-0.94.3, 正常执行 接下来,安装Hive,基于已经安装好的hadoop.过程 ...

  10. Android——4.2 - 3G移植之路之 reference-ril .pppd 拨号上网 (三)

    Android的RIL机制中的 reference-ril.c 即为厂商提供的驱动接口.这个驱动源代码各个厂商都是有提供的,网上也有下载.我如今用的就是huawei wcdma的.最后编译成libre ...