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();
}
}<