网上有很多AutoResetEvent和ManualResetEvent的详细介绍,在这里不做过多详细的解释,写下自己的一点心得留作备忘。

AutoResetEvent和ManualResetEvent都是事件锁,事件的功能就是可以在被监控者发生某种变化后立即通知监控者并做出相应反应。

在使用多线程过程中,锁几乎是不可缺少的一项,我们拿信号量和事件锁举例来说。

如果有一个厨师和一群顾客,如果是使用信号量的话,情况如下:顾客询问厨师:“饭做好了吗?”,厨师:“还没有好,等一会吧!”,顾客继续等待一段时间后继续询问,循环往复,直到饭做好后开始吃饭。

如果采用事件锁的话,情况如下:厨师告诉顾客:“你先等一会吧,饭做好后,我告诉你!”,顾客等待,厨师告诉顾客:“饭做好了,你过来吃吧!”,顾客吃饭。在这种模式下,使用事件锁就会好一些。

AutoResetEvent myAutoRetEvent = new AutoResetEvent(false);

ManualResetEvent myManualRetEvent = new ManualResetEvent(false);

//通知正在等待的线程已发生事件(厨师)

//构造函数函数变量如果为:false,初始状态非终止状态。厨师的初始状态就很忙碌,顾客如果要吃饭就要等待。

//构造函数变量如果为:true,初始状态为终止状态。厨师的初始状态为已经做好了饭,顾客可以直接吃饭。

/// <summary>
/// 通知正在等待的线程已发生事件 true:初始状态为终止状态 false:初始状态为非终止状态
/// 目前的初始状态未厨师没有做饭
/// </summary>
private AutoResetEvent myAutoRetEvent = new AutoResetEvent(false); private void button2_Click(object sender, EventArgs e)
{
Thread myThread = new Thread(new ThreadStart(RunStart));
myThread.Start();
//厨师做饭做了3000ms
Thread.Sleep();
//厨师告诉顾客饭做好了
myAutoRetEvent.Set();
} private void RunStart()
{
//顾客来了,要吃饭
myAutoRetEvent.WaitOne();
MessageBox.Show("吃饭...");
}

单击按钮后,等待3秒后,弹出“吃饭...”,如果把构造函数中的false改为true,单击按钮后,立即弹出“吃饭...”。

而ManualResetEvent与AutoResetEvent的区别是:前者(厨师做好饭后,所有的顾客都开始吃饭),而后者(厨师做好饭后,只有一个顾客能吃到饭。)

AutoResetEvent:

/// <summary>
/// 通知正在等待的线程已发生事件 true:初始状态为终止状态 false:初始状态为非终止状态
/// 目前的初始状态未厨师没有做饭
/// </summary>
private AutoResetEvent myAutoRetEvent = new AutoResetEvent(false); private void button3_Click(object sender, EventArgs e)
{
//来了一个顾客1
Thread myThread1 = new Thread(new ThreadStart(Run_1));
myThread1.Start();
//来了一个顾客2
Thread myThread2 = new Thread(new ThreadStart(Run_2));
myThread2.Start(); //厨师做饭做3000ms
Thread.Sleep();
//厨师做好饭了,通知看谁能吃上饭
myAutoRetEvent.Set();
} private void Run_1()
{
//顾客1过来了,要吃饭,等厨师做好饭
myAutoRetEvent.WaitOne();
MessageBox.Show("我是顾客1开始吃饭...");
} private void Run_2()
{
//顾客2过来了,要吃饭,等厨师做好饭
myAutoRetEvent.WaitOne();
MessageBox.Show("我是顾客2开始吃饭...");
}

ManualResetEvent:

private ManualResetEvent myManualRetEvent = new ManualResetEvent(false);

        private void button4_Click(object sender, EventArgs e)
{
//来了一个顾客1
Thread myThread3 = new Thread(new ThreadStart(Run_3));
myThread3.Start();
//来了一个顾客2
Thread myThread4 = new Thread(new ThreadStart(Run_4));
myThread4.Start(); //厨师做饭做3000ms
Thread.Sleep();
//厨师做好饭了,通知看谁能吃上饭
myManualRetEvent.Set();
} private void Run_3()
{
//顾客1过来了,要吃饭,等厨师做好饭
myManualRetEvent.WaitOne();
MessageBox.Show("我是顾客1开始吃饭...");
} private void Run_4()
{
//顾客2过来了,要吃饭,等厨师做好饭
myManualRetEvent.WaitOne();
MessageBox.Show("我是顾客2开始吃饭...");
}

厨师做好饭后,通知大家,所有等待的顾客都开始吃饭。两者的区别如上所述。

此篇文章是受csdn 陆敏技的文章启发,便于自己的理解记忆。

05-11 15:41