C#多线程AutoResetEvent与ManualResetEvent(转)

AutoResetEvent与ManualResetEvent区别

新一篇: AutoResetEvent详解

在.Net多线程编程中,AutoResetEvent和ManualResetEvent这两个类经常用到, 他们的用法很类似,但也有区别。Set方法将信号置为发送状态,Reset方法将信号置为不发送状态,WaitOne等待信号的发送。可以通过构造函数的 参数值来决定其初始状态,若为true则非阻塞状态,为false为阻塞状态。如果某个线程调用WaitOne方法,则当信号处于发送状态时,该线程会得 到信号, 继续向下执行。其区别就在调用后,AutoResetEvent.WaitOne()每次只允许一个线程进入,当某个线程得到信号 后,AutoResetEvent会自动又将信号置为不发送状态,则其他调用WaitOne的线程只有继续等待.也就是说,AutoResetEvent 一次只唤醒一个线程;而ManualResetEvent则可以唤醒多个线程,因为当某个线程调用了ManualResetEvent.Set()方法 后,其他调用WaitOne的线程获得信号得以继续执行,而ManualResetEvent不会自动将信号置为不发送。也就是说,除非手工调用了 ManualResetEvent.Reset()方法,则ManualResetEvent将一直保持有信号状态,ManualResetEvent也 就可以同时唤醒多个线程继续执行。

Mutex和AutoResetEvent和ManualResetEvent

    

AutoResetEvent
AutoResetEvent myResetEvent = new AutoResetEvent(false);
myResetEvent.WaitOne();
//waite other thread1 complete
myResetEvent
.WaitOne();
//waite other thread2 complete
myResetEvent
.WaitOne();
run current thread;

//in other thread run
myResetEvent.Set();

在下个WaitOne之前会自动Reset(),阻止执行。即当执行到第二个myResetEvent.WaitOne()时,会终止当前thread,等待myResetEvent.set()

ManualResetEvent
ManualResetEvent manualEvent = new ManualResetEvent(false);
//waite other thread1 complete
manualEvent.WaitOne();
//waite other thread2 complete
manualEvent.WaitOne();
run current thread;
//in other thread run
manualEvent.Set();

需手动Reset(),如果不执行Reset(),第二个WaitOne()将不会再次等待。
AutoResetEvent 类.set() 方法的问题

悬赏分:0 - 解决时间:2008-4-30 15:04
AutoResetEvent 类.set() 方法的问题
csdn上说
将事件状态设为终止,允许等待的一个或多个线程继续。什么意思
提问者: ericostock - 助理 三级
最佳答案
线程通过调用 AutoResetEvent 上的 WaitOne 来等待信号。如果 AutoResetEvent 处于非终止状态,则该线程阻塞,并等待当前控制资源的线程通过调用 Set 发出资源可用的信号。

调用 Set 向 AutoResetEvent 发信号以释放等待线程。AutoResetEvent 将保持终止状态,直到一个正在等待的线程被释放,然后自动返回非终止状态。如果没有任何线程在等待,则状态将无限期地保持为终止状态。
AutoResetEvent 与 ManualResetEvent
2006年12月20日 星期三 10:30

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

当线程开始一个活动(此活动必须在其他线程进行之前完成)时,它调用 ResetManualResetEvent 设置为非终止状态。此线程可被视为控制 ManualResetEvent
调用 ManualResetEvent 上的 WaitOne 的线程将阻塞,并等待信号。
当控制线程完成活动时,它调用 Set 以发出等待线程可以继续进行的信号。并释放所有等待线程。
一旦它被终止,ManualResetEvent 将保持终止状态,直到它被手动重置。即对 WaitOne 的调用将立即返回。

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

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

摘自http://msdn.micr
osoft.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();
}
}<

Mutex
        m.WaitOne();
      
try {
          Console.WriteLine(
"Start Resource access (Thread={0})", threadNum);
          Thread.Sleep(
500);
          Console.WriteLine(
"Stop   Resource access (Thread={0})", threadNum);
       }

      
finally {
          m.ReleaseMutex();

posted @ 2011-02-25 15:36  董雨  阅读(537)  评论(0编辑  收藏  举报