示例
两个线程交替输出“1 a 2 b 3 c 4 d 5 .....”
代码
//利用ManualResetEvent和AutoResetEvent交替输出“1 a 2 b 3 c 4 d 5 .....”
//ManualResetEvent和AutoResetEvent不同点:
//AutoResetEvent 收到 Set 后 , 一次只能执行一个线程,其它线程继续 WaitOne
//ManualResetEvent 收到 Set 后,所有处理 WaitOne 状态线程均继续执行
//AutoResetEvent.Set() = ManualResetEvent.Set() + ManualResetEvent.Reset();
//在.Net多线程编程中,AutoResetEvent和ManualResetEvent这两个类经常用到, 他们的用法很类似,但也有区别。Set方法将信号置为发送状态,
//Reset方法将信号置为不发送状态,WaitOne等待信号的发送。可以通过构造函数的参数值来决定其初始状态,若为true则非阻塞状态,为false为阻塞状态。
//如果某个线程调用WaitOne方法,则当信号处于发送状态时,该线程会得到信号, 继续向下执行。其区别就在调用后,AutoResetEvent.WaitOne() 每次只允许一个线程进入,
//当某个线程得到信号后, AutoResetEvent会自动又将信号置为不发送状态, 则其他调用WaitOne的线程只有继续等待.
//也就是说,AutoResetEvent一次只唤醒一个线程;而ManualResetEvent则可以唤醒多个线程,因为当某个线程调用了ManualResetEvent.Set() 方法后,
//其他调用WaitOne的线程获得信号得以继续执行, 而ManualResetEvent不会自动将信号置为不发送。也就是说,除非手工调用了ManualResetEvent.Reset() 方法,
//则ManualResetEvent将一直保持有信号状态, ManualResetEvent也就可以同时唤醒多个线程继续执行。
//本质上AutoResetEvent.Set() 方法相当于ManualResetEvent.Set()+ManualResetEvent.Reset();
//因此AutoResetEvent一次只能唤醒一个线程,其他线程还是堵塞
class Program
{
private static List<ManualResetEvent> _listManual = new List<ManualResetEvent>();
private static List<AutoResetEvent> _listAuto = new List<AutoResetEvent>();
private static List<int> _listNumber = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
private static List<char> _listLetter = new List<char>() { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' };
//private static List<char> _listUpperLetter = new List<char>() { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J' };
static void Main(string[] args)
{
#region ManualResetEvent
_listManual.Add(new ManualResetEvent(false));//用于控制_listNumber的信号灯
_listManual.Add(new ManualResetEvent(false));//用于控制_listLetter的信号灯
Task.Run(() =>
{
_listNumber.ForEach(c =>
{
_listManual[0].WaitOne();
Console.WriteLine(c);
_listManual[0].Reset();
_listManual[1].Set();
});
});
Task.Run(() =>
{
_listLetter.ForEach(c =>
{
_listManual[1].WaitOne();
Console.WriteLine(c);
_listManual[0].Set();
_listManual[1].Reset();
});
});
_listManual[0].Set();
Console.ReadKey();
#endregion
#region AutoResetEvent
_listAuto.Add(new AutoResetEvent(false));//用于控制_listNumber的信号灯
_listAuto.Add(new AutoResetEvent(false));//用于控制_listLetter的信号灯
Task.Run(() =>
{
_listNumber.ForEach(c =>
{
_listAuto[0].WaitOne();
Console.WriteLine(c);
_listAuto[1].Set();
//不需要ReSet,因为AutoResetEvent在某个wait的线程得到信号后会自动变为ReSet,WaitOne每次只允许一个线程进入
});
});
Task.Run(() =>
{
_listLetter.ForEach(c =>
{
_listAuto[1].WaitOne();
Console.WriteLine(c);
_listAuto[0].Set();
});
});
_listAuto[0].Set();
Console.ReadKey();
#endregion
}
}
//Reset() //红灯
//Set() //绿灯
//WaitOne() // 等待信号
输出