今天在写code时发现了原来代码里有一个AutoResetEvent,于是就研究了一下它的用法,这里做一下笔记。
AutoResetEvent根据我的理解,是做线程互斥时所使用的信号量,在有独占资源时使用,它提供了一对方法,WaitOne()与Set(),用以阻塞线程进入等待状态与发出信号让阻塞的线程放行,WaitOne()就像一个闸门,程序执行到这里会被阻塞,直到Set()方法被别的线程调用,发出信号,闸门打开,阻塞的线程才会继续执行,否则会一直等待下去。
这里使用了一个别人的例子,稍加修改,假设我现在要买书,买书分为三个步骤,决定要买的书(挑书),付钱,取书3步,由于我只有一个人,所以一次只能做一步,相当于独占资源,每做完一步,通知下个步骤进行,否则就处于阻塞状态。
我用3个线程来模拟,主线程选书,然后两个子线程模拟付钱和取书。代码如下:
class Program
{
static AutoResetEvent buyEvent = new AutoResetEvent(false);//选书信号量
static AutoResetEvent payEvent = new AutoResetEvent(false);//付钱信号量
static AutoResetEvent getEvent = new AutoResetEvent(true);//取书信号量,注意为true,第一次直接放行
const int bookCount = 10;//一共买10本书
static int bookNum = 0;//当前第几本书
static void Main(string[] args)
{
Thread payThread = new Thread(PayThread);//付钱线程
Thread getThread = new Thread(GetThread);//取书线程
payThread.Start();
getThread.Start();
for (int i = 1; i <= bookCount; i++) //开始选书
{
getEvent.WaitOne(); //等待取书完成
bookNum = i;
Console.WriteLine("Buy {0} book", bookNum); //选书
buyEvent.Set(); //选书完成
}
//wait for the last getEvent return
getEvent.WaitOne(); //等待最后一次取书完成,不然子线程还没跑完就被下面两个语句杀掉了
payThread.Abort(); //付钱线程终止
getThread.Abort(); //取书线程终止
Console.Read();
}
static void PayThread()
{
while (true)
{
buyEvent.WaitOne(); //等待选书完成
Console.WriteLine("Pay {0} book", bookNum); //付钱
payEvent.Set(); //付钱完成
}
}
static void GetThread()
{
while (true)
{
payEvent.WaitOne(); //等待付钱完成
Console.WriteLine("Get {0} book", bookNum); //取书
getEvent.Set(); //取书完成
}
}
}
代码里有两点需要注意的地方
1.在 getEvent 初始化时,我们把它设置为true,这是为了在第一次选书时能够顺利放行,因为第一次选书不需要等待取书完成。
2.在两个子进程结束之前,调用一次getEvent.WaitOne()这是确保最后一次取书能够执行完,不然子线程还没有处理完就被主线程杀掉了。
好了,这就是一个WaitOne和AutoResetEvent的简单应用,下面是一些参考链接:
http://blog.csdn.net/lanruoshui/article/details/5411270
http://msdn.microsoft.com/zh-cn/library/system.threading.autoresetevent.aspx