AutoResetEvent 与 ManualResetEvent

lResetEvent 允许线程通过发信号互相通信。通常,此通信涉及一个线程在其他线程进行之前必须完成的任务。

当线程开始一个活动(此活动必须在其他线程进行之前完成)时,它调用 Reset 将ManualResetEvent 设置为非终止状态。此线程可被视为控制 ManualResetEvent

 

调用 ManualResetEvent 上的 WaitOne 的线程将阻塞,并等待信号。

 

当控制线程完成活动时,它调用 Set 以发出等待线程可以继续进行的信号。并释放所有等待线程。

一旦它被终止,ManualResetEvent 将保持终止状态,直到它被手动重置。即对 WaitOne 的调用将立即返回。

可以通过将布尔值传递给构造函数来控制 ManualResetEvent 的初始状态,如果初始状态处于终止状态,为 true;否则为 false。

ManualResetEvent 还可以和静态(在 Visual Basic 中为 Shared)WaitAll 和 WaitAny 方法一起使用。

摘自http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/cpref/html/frlrfsystemthreadingmanualreseteventclasstopi 

AutoResetEvent 与 ManualResetEvent区别 

在C#多线程编程中,这两个类几乎是不可或缺的,他们的用法/声明都很类似,那么区别在哪里了?

Set方法将信号置为发送状态 Reset方法将信号置为不发送状态 WaitOne等待信号的发送

其实,从名字就可以看出一点端倪  ,一个手动,一个自动,这个手动和自动实际指的是在Reset方法的处理上,如下面例子

public AutoResetEvent autoevent=new AutoResetEvent(true);

public ManualResetEvent manualevent=new ManualResetEvent(true);

默认信号都处于发送状态,

autoevent.WaitOne();

manualevent.WaitOne();

如果 某个线程调用上面该方法,则当信号处于发送状态时,该线程会得到信号,得以继续执行

差别就在调用后,autoevent.WaitOne()每次只允许一个线程进入,当某个线程得到信号(也就是有其他线程调用了autoevent.Set()方法后)后,autoevent会自动又将信号置为不发送状态,则其他调用WaitOne的线程只有继续等待.也就是说,autoevent一次只唤醒一个线程

而manualevent则可以唤醒多个线程,因为当某个线程调用了set方法后,其他调用waitone的线程获得信号得以继续执行,而manualevent不会自动将信号置为不发送.也就是说,除非手工调用了anualevent.Reset().方法,则manualevent将一直保持有信号状态,manualevent也就可以同时唤醒多个线程继续执行


Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=547166

 

AutoResetEvent:自动调用this.Reset(),设置不发送信号,则等待信号(waitone())的线程将不执行。
ManualResetEvent:需要编程者调用this.Reset来设置不发送信号状态,以阻止其他线程的执行。

 

这个在SOCKET编程中的异步套接字的时候   
  private   static   ManualResetEvent   connectDone   =   new   ManualResetEvent(false);   
  private   static   ManualResetEvent   sendDone   =   new   ManualResetEvent(false);   
  private   static   ManualResetEvent   receiveDone   =   new   ManualResetEvent(false);   
    
  public   void   StartClient()   
  {   
  IPAddress   ipAddress   =   IPAddress.Parse(strIPAddress);   
  IPEndPoint   remoteEP   =   new   IPEndPoint(ipAddress,vodPort);   
  Socket   client   =   new   Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);   
    
  client.BeginConnect(remoteEP,new   AsyncCallback(ConnectCallBack),client);   
  connectDone.WaitOne();   
    
  Send(client,((VodMsg)SendMsg[0]).ToString());   
  SendMsg.Remove(SendMsg[0]);   
  sendDone.WaitOne();   
    
  Receive(client);   
  receiveDone.WaitOne();   
    
  client.Shutdown(SocketShutdown.Both);   
  client.Close();   
  }   
    
  然后在Connect、Send、Receive、的回调函数里分别设置状态为.Set(),以便线程继续运行。   
  这样,Send以前可以保证连接已经建立,Receive前可以保证消息已经发送,关闭前可以保证消息已经接收。不会出现运行Receive的回调函数的时候Socket已经关闭了。 

 

在串口类里面:   
    
  //   Delegate   class   declarations.   
  public   delegate   void   VoidFunc();   
  public   delegate   void   BoolFunc(bool   b);   
  public   delegate   void   StrnFunc(string   s);   
  public   delegate   void   ByteFunc(byte[]   b);   
    
  ///   <summary>   
  ///   This   structure   contains   one   delegate   method   for   each   override   event   
  ///   method   in   the   serial   port   base   class.   Each   delegate   provides   a   hook   
  ///   that   can   be   used   by   any   application   that   wishes   to   connect   to   the   
  ///   asynchronous   OnXXX   methods.   
  ///   </summary>   
  public   struct   WithEvents   
  {   
  public   VoidFunc   Break;   
  public   VoidFunc   TxDone;   
  public   StrnFunc   Error;   
  public   ByteFunc   RxChar;   
  public   BoolFunc   CtsSig;   
  public   BoolFunc   DsrSig;   
  public   BoolFunc   RlsdSig;   
  public   BoolFunc   RingSig;   
  }   
    
  ...   
  public   class   SerialPort   
  {   
  private   WithEvents   ev;   
  private   ManualResetEvent   recvrEvent;//接收数据线程启动的信号   
  private   ManualResetEvent   writeEvent;   
  private   Thread   rxThread;   //接收数据的线程   
  public   SerialPort(WithEvents   ev)   
  {   
        this.ev   =   ev;   
  }   
  //打开串口   
  protected   bool   Open(...)   //就是我前面调用的this.Port.Open   
  {   
        ...   
        this.recvrEvent   =   new   ManualResetEvent(false);   
        ...   
        //启动线程     
        this.rxThread   =   new   Thread(new   ThreadStart(ReceiveThread));   
        this.rxThread.Priority   =   ThreadPriority.AboveNormal;   
        this.rxThread.Start();   
        //   Wait   for   receive   thread   to   start.   
        this.recvrEvent.WaitOne(500,   false);   
        //成功打开了串口   
          
  }   
  private   void   ReceiveThread()   
  {   
          //接收数据   
          //触发事件   
          ...   
          this.OnRxChar(buf);   
  }   
  }   

 

System;
using System.Threading;

namespace ManualReset
{

class Reset
{

[STAThread]
static void Main()
{
ManualResetEvent manRE;
manRE = new ManualResetEvent(true); // 赋给信号量
bool state = manRE.WaitOne(1000, true);
Console.WriteLine("ManualResetEvent After first waitone " + state);

manRE.Reset(); //设置ManualResetEvent状态为无信号量
state = manRE.WaitOne(5000, true);
Console.WriteLine("ManualResetEvent After second waitone " + state);

Console.Read();
}
}
}


using System;
using System.Threading;
namespace ManualSet
{

class Set
{

[STAThread]
static void Main(string[] args)
{
ManualResetEvent manRE;
manRE = new ManualResetEvent(false);
Console.WriteLine("Before waitone");
bool state = manRE.WaitOne(5000, true);
Console.WriteLine("ManualResetEvent After first waitone " + state);

manRE.Set(); //将其状态设为有信号量
Thread.Sleep(3000);
state = manRE.WaitOne(5000, true);
Console.WriteLine("ManualResetEvent After second waitone " + state);
Console.Read();
}
}< 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值