C#线程间互相通信主要用到两个类:AutoResetEvent和ManualResetEvent.
  一、AutoResetEvent
  AutoResetEvent 允许线程通过发信号互相通信,线程通过调用 AutoResetEvent 上的 WaitOne 来等待信号。 如果 AutoResetEvent 为非终止状态,则线程会被阻止,并等待当前控制资源的线程通过调用 Set 来通知资源可用。
  下面我用吃快餐的例子来说明这个问题,吃快餐的时候都会排队付款,收银员发送收款通知,客户依次付钱,代码如下:
  复制代码
  1 class Program
  2 {
  3 //若要将初始状态设置为终止,则为 true;若要将初始状态设置为非终止,则为 false
  4 static AutoResetEvent autoResetEvent = new AutoResetEvent(false);
  5
  6 static void Main(string[] args)
  7 {
  8 Thread t1 = new Thread(() =>
  9 {
  10 Console.WriteLine("客户1在排队等待付钱…");
  11
  12 //客户1调用AutoResetEvent上的WaitOne来等待付钱通知
  13 autoResetEvent.WaitOne();
  14 Console.WriteLine("通知来了,客户1付钱");
  15 });
  16 t1.IsBackground = true;
  17 t1.Start();
  18
  19 Pay();//发送通知
  20 Console.ReadKey();
  21 }
  22
  23 static void Pay()
  24 {
  25 string tip = Console.ReadLine();
  26 if (tip == "next")
  27 {
  28 autoResetEvent.Set();//收银员发送付钱通知,通过调用Set来通知客户付钱
  29 }
  30 }
  31 }
  复制代码
  运行在屏幕中打印:
  客户1在排队等待付钱…
  等收银员说"next"的时候,向客户1发送付钱通知(autoResetEvent.Set()),屏幕打印:
  客户1在排队等待付钱…
  next
  通知来了,客户1付钱!
  AutoResetEvent类一次只能通知一个等待的线程,且通知一次过后会立即将AutoResetEvent对象的状态置为false,也就是如果有两个客户都在等待收银员通知,AutoResetEvent对象的set方法只能通知到第一个客户,代码和效果如下:
  复制代码
  1 class Program
  2 {
  3 //若要将初始状态设置为终止,则为 true;若要将初始状态设置为非终止,则为 false.
  4 static AutoResetEvent autoResetEvent = new AutoResetEvent(false);
  5
  6 static void Main(string[] args)
  7 {
  8 Thread t1 = new Thread(() =>
  9 {
  10 Console.WriteLine("客户1在排队等待付钱…");
  11
  12 //客户1调用AutoResetEvent上的WaitOne来等待付钱通知
  13 autoResetEvent.WaitOne();
  14 Console.WriteLine("通知来了,客户1付钱");
  15 });
  16 t1.IsBackground = true;
  17 t1.Start();
  18
  19 Thread t2 = new Thread(() =>
  20 {
  21 Console.WriteLine("客户2在排队等待付钱…");
  22
  23 //客户2调用AutoResetEvent上的WaitOne来等待付钱通知
  24 autoResetEvent.WaitOne();
  25 Console.WriteLine("通知来了,客户2付钱!");
  26 });
  27 t2.IsBackground = true;
  28 t2.Start();
  29
  30 Pay();//发送通知
  31
  32 Console.ReadKey();
  33 }
  34
  35 static void Pay()
  36 {
  37 string tip = Console.ReadLine();
  38 if (tip == "next")
  39 {
  40 autoResetEvent.Set();//收银员发送付钱通知,通过调用Set来通知客户付钱
  41 }
  42 }
  43 }
  复制代码
  运行后屏幕打印:
  客户1在排队等待付钱…
  客户1在排队等待付钱…
  next
  通知来了,客户1付钱!
  这就说明在通知完客户1后,autoResetEvent 的状态又被置为了false,这时如果要通知到客户2,就需要在通知完客户1后,再执行一次通知,在线程1中加上一行代码,如下:
  复制代码act答案 www.yzyxedu.com
  1 Thread t1 = new Thread(() =>
  2 {
  3 Console.WriteLine("客户1在排队等待付钱…");
  4
  5 //客户1调用AutoResetEvent上的WaitOne来等待付钱通知
  6 autoResetEvent.WaitOne();
  7 Console.WriteLine("通知来了,客户1付钱");
  8
  9 autoResetEvent.Set();//让其再通知下个客户
  10 });
  复制代码
  运行后屏幕打印:
  客户1在排队等待付钱…
  客户1在排队等待付钱…
  next
  通知来了,客户1付钱!
  通知来了,客户2付钱!
  这也就说明每调用一次Set,只有一个线程会解除等待,换句话说,有多少个线程就要调用多少次Set,线程才会全部继续。
  二、ManualResetEvent
  在AutoResetEvent中,如果要通知两个线程,则Set方法要被执行两次,也以快餐店的例子做了举例,但如果有一天客户1中彩票了,要请部门的10个同事吃饭,也就是说只要Set一次,所有在等待的线程都会解除等待,相当于收银员只收一次钱,10个人都可以通过收银去吃饭,这时我们就要用到ManualResetEvent类,它的用法和AutoResetEvent基本一样,区别就在于它是一量Set方法发出通知后,要再次阻塞的话就需要手动去修改,也就是调用Reset方法,代码如下:
  复制代码
  1 class Program
  2 {
  3 //若要将初始状态设置为终止,则为 true;若要将初始状态设置为非终止,则为 false.
  4 static ManualResetEvent manualResetEvent = new ManualResetEvent(false);
  5
  6 static void Main(string[] args)
  7 {
  8 Thread t1 = new Thread(() =>
  9 {
  10 Console.WriteLine("客户1在排队等待付钱…");
  11
  12 //客户1调用manualResetEvent上的WaitOne来等待付钱通知
  13 manualResetEvent.WaitOne();
  14 Console.WriteLine("已经有人请客,客户1不用付钱");
  15 });
  16 t1.IsBackground = true;
  17 t1.Start();
  18
  19 Thread t2 = new Thread(() =>
  20 {
  21 Console.WriteLine("客户2在排队等待付钱…");
  22
  23 //客户2调用manualResetEvent上的WaitOne来等待付钱通知
  24 manualResetEvent.WaitOne();
  25 Console.WriteLine("已经有人请客,客户2不用付钱!");
  26 });
  27 t2.IsBackground = true;
  28 t2.Start();
  29
  30 Pay();//发送通知
  31
  32 Console.ReadKey();
  33 }
  34
  35 static void Pay()
  36 {
  37 string tip = Console.ReadLine();
  38 if (tip == "next")
  39 {
  40 manualResetEvent.Set();//收银员发送付钱通知,通过调用Set来通知客户付钱
  41 }
  42 }
  43 }
  复制代码
  运行后屏幕打印:
  客户1在排队等待付钱…
  客户1在排队等待付钱…
  next
  已经有人请客,客户1不用付钱!
  已经有人请客,客户2不用付钱!
  如果收银员在发送通知后5秒就下班了,就不能再收钱了,这时就要把通知重置掉,让没接到通知的客户继续处于继续等待,代码如下:
  复制代码
  1 class Program
  2 {
  3 //若要将初始状态设置为终止,则为 true;若要将初始状态设置为非终止,则为 false.
  4 static ManualResetEvent manualResetEvent = new ManualResetEvent(false);
  5
  6 static void Main(string[] args)
  7 {
  8 Thread t1 = new Thread(() =>
  9 {
  10 Console.WriteLine("客户1在排队等待付钱…");
  11
  12 //客户1调用manualResetEvent上的WaitOne来等待付钱通知
  13 manualResetEvent.WaitOne();
  14 Console.WriteLine("已经有人请客,客户1不用付钱");
  15 });
  16 t1.IsBackground = true;
  17 t1.Start();
  18
  19 Thread t2 = new Thread(() =>
  20 {
  21 Console.WriteLine("客户2在排队等待付钱…");
  22
  23 Thread.Sleep(8000);//客户2发呆了8秒,这时收银员已经下班,要继续等待
  24 //客户2调用manualResetEvent上的WaitOne来等待付钱通知
  25 manualResetEvent.WaitOne();
  26 Console.WriteLine("已经有人请客,客户2不用付钱!");
  27 });
  28 t2.IsBackground = true;
  29 t2.Start();
  30
  31 Pay();//发送通知
  32
  33 Console.ReadKey();
  34 }
  35
  36 static void Pay()
  37 {
  38 string tip = Console.ReadLine();
  39 if (tip == "next")
  40 {
  41 manualResetEvent.Set();//收银员发送付钱通知,通过调用Set来通知客户付钱
  42
  43 Timer timer = new Timer(StopPay, null, 0, 5000);//5秒钟后收银员下班了,线程要重新等待了
  44 }
  45 }
  46
  47 static void StopPay(object s)
  48 {
  49 manualResetEvent.Reset();
  50 Console.WriteLine("收银员下班, 后面的客户要继续等待");
  51 }
  52 }
  复制代码
  运行后屏幕打印:
  客户1在排队等待付钱…
  客户1在排队等待付钱…
  next
  已经有人请客,客户1不用付钱!
  收银员下班,后面的客户要继续等待
  总结
  AutoResetEvent和ManualResetEvent的主要区别就在于:AutoResetEvent一次只能通知一个等待线程,通知后自动关闭; 而ManualResetEvent一次可通知很多个等待的线程,但要关闭需要调用Reset方法手动关闭托福答案 www.yztrans.com

C# 线程间互相通信的更多相关文章

  1. iOS开发多线程篇—线程间的通信

    iOS开发多线程篇—线程间的通信 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任 ...

  2. Java核心知识点学习----多线程并发之线程间的通信,notify,wait

    1.需求: 子线程循环10次,主线程循环100次,这样间隔循环50次. 2.实现: package com.amos.concurrent; /** * @ClassName: ThreadSynch ...

  3. java多线程详解(6)-线程间的通信wait及notify方法

    Java多线程间的通信 本文提纲 一. 线程的几种状态 二. 线程间的相互作用 三.实例代码分析 一. 线程的几种状态 线程有四种状态,任何一个线程肯定处于这四种状态中的一种:(1). 产生(New) ...

  4. iOS边练边学--多线程NSOperation介绍,子类实现多线程的介绍(任务和队列),队列的取消、暂停(挂起)和恢复,操作依赖与线程间的通信

    一.NSOperation NSOperation和NSOperationQueue实现多线程的具体步骤 先将需要执行的操作封装到一个NSOperation对象中 然后将NSOperation对象添加 ...

  5. 新建线程与UI线程间的通信

    现在用一个实例来演示一下自己的新建线程与UI线程间的通信. UI界面包含3个控件: 一个输入框,用来输入数字: 一个显示框,用来显示从2开始,到输入数字之间的所有质数: 一个按钮,点击后获取输入框输入 ...

  6. QThread与其他线程间相互通信

    转载请注明链接与作者huihui1988 QThread的用法其实比较简单,只需要派生一个QThread的子类,实现其中的run虚函数就大功告成, 用的时候创建该类的实例,调用它的start方法即可. ...

  7. Handler不同线程间的通信

    转http://www.iteye.com/problems/69457 Activity启动后点击一个界面按钮后会开启一个服务(暂定为padService),在padService中会启动一个线程( ...

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

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

  9. C# 线程间互相通信 AutoResetEvent和ManualResetEvent

    C#线程间互相通信主要用到两个类:AutoResetEvent和ManualResetEvent. 一.AutoResetEvent AutoResetEvent 允许线程通过发信号互相通信,线程通过 ...

随机推荐

  1. (转载)Mysql中,SQL语句长度限制

    (转载)http://qjoycn.iteye.com/blog/1288435 今天发现了一个错误:Could not execute JDBC batch update 最后发现原因是SQL语句长 ...

  2. JQuery中如何click中传递参数

    代码如下: click(data,fn)中的data其实是json对象,取的时候,只能通过当前的事件源来取,data是默认放在event中的,所以这里的data是eventdata,引用的时候也使用e ...

  3. HDU-1969 Pie

    http://acm.hdu.edu.cn/showproblem.php?pid=1969 Pie Time Limit: 5000/1000 MS (Java/Others)    Memory ...

  4. 《University Calculus》-chaper13-多重积分-二重积分的计算

    之前关于二重积分的笔记,介绍了二重积分概念的引入,但是对于它的计算方法(化为累次积分),介绍的较为模糊,它在<概率论基础教程>中一系列的推导中发挥着很重要的作用. 回想先前关于二重积分的几 ...

  5. 2 hive的使用 + hive的常用语法

    本博文的主要内容有: .hive的常用语法 .内部表 .外部表 .内部表,被drop掉,会发生什么? .外部表,被drop掉,会发生什么? .内部表和外部表的,保存的路径在哪? .用于创建一些临时表存 ...

  6. 自己生成非官方iPhone toolchain的头文件

    如果你已经搭建好非官方iPhone toolchain开发包,如果缺少某些头文件,可以用以下方法自己生成. 首先下载class-dump: http://www.codethecode.com/pro ...

  7. JDK JRE JVM

    使用java很久,但是一直不清楚JDK,JRE,JVM直接的关系,今天特地梳理一下. JDK:Java Development ToolKit(Java开发工具包),JDK是整个JAVA的核心,包括J ...

  8. PDO 提供了三种不同的错误处理模式

    PDO::ERRMODE_SILENT 此为默认模式. PDO 将只简单地设置错误码,可使用 PDO::errorCode() 和 PDO::errorInfo() 方法来检查语句和数据库对象.如果错 ...

  9. libcurl使用演示样例

    简要说明:C++使用libcurl訪问"www.baidu.com".获取返回码和打印出http文件 /* * @ libcurl使用演示样例 * @ 2014.04.29 * @ ...

  10. Python异常处理 分类: python Raspberry Pi 服务器搭建 2015-04-01 13:22 172人阅读 评论(0) 收藏

    一个程序要保持稳定运行必须要有异常处理,本文将简单介绍Python中的try-except..异常处理语句的使用. 该种异常处理语法的规则是: 执行try下的语句,如果引发异常,则执行过程会跳到第一个 ...