static void EventWaitHandleTest2(EventResetMode mode)
{
EventWaitHandle r1 = new EventWaitHandle(false, mode);
Thread t1 = new Thread(delegate()
{
while (true)
{
r1.WaitOne();
Console.WriteLine("1");
Thread.Sleep(1000);
//r1.Reset();
//r1.Set();
}
}
);
t1.Start();
r1.Set();
}
{
EventWaitHandle r1 = new EventWaitHandle(false, mode);
Thread t1 = new Thread(delegate()
{
while (true)
{
r1.WaitOne();
Console.WriteLine("1");
Thread.Sleep(1000);
//r1.Reset();
//r1.Set();
}
}
);
t1.Start();
r1.Set();
}
当我们使用 EventWaitHandleTest2(EventResetMode.AutoReset); 调用该方法时,我们发现循环体在执行一次后并没有继续,线程被阻塞。而 EventWaitHandleTest2(EventResetMode.ManualReset); 调用时则不会阻塞,循环体无限执行下去。由此我们可以区别这两种状态的不同,自动方式会自动将同步状态设置为非终止,而手动则不会。自动状态时,我们删除 r1.Set(); 行的注释字符 (//),将状态重置为终止状态,则循环体自动进行下一轮执行;手动方式,我们将 r1.Reset(); 行的注释行删除,那么同步状态会被重置为非终止状态状态,那么线程体自然被阻塞,不会继续循环体的执行了。
.net Framework 2.0 的 AutoResetEvent 和 ManualResetEvent 继承自 EventWaitHandle,而不是 1.x 中继承自 WaitHandle。这两个类只是重写了构造方法而已。
public AutoResetEvent(bool initialState) : base(initialState, EventResetMode.AutoReset)
{
}
public ManualResetEvent(bool initialState) : base(initialState, EventResetMode.ManualReset)
{
}
{
}
public ManualResetEvent(bool initialState) : base(initialState, EventResetMode.ManualReset)
{
}
接下来,我们另写一个例子。让两个线程交替执行。
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void EventWaitHandleTest(EventResetMode mode)
{
EventWaitHandle r1 = new EventWaitHandle(false, mode);
EventWaitHandle r2 = new EventWaitHandle(false, mode);
Thread t1 = new Thread(delegate()
{
while (true)
{
r1.WaitOne();
Console.WriteLine("1");
Thread.Sleep(1000);
if (mode == EventResetMode.ManualReset) r1.Reset();
r2.Set();
}
}
);
Thread t2 = new Thread(delegate()
{
while (true)
{
r2.WaitOne();
Console.WriteLine("2");
if (mode == EventResetMode.ManualReset) r2.Reset();
r1.Set();
}
}
);
t1.Start();
t2.Start();
r1.Set();
}
static void Main()
{
EventWaitHandleTest(EventResetMode.AutoReset);
Console.WriteLine("Press any key to exit...");
Console.ReadKey(true);
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void EventWaitHandleTest(EventResetMode mode)
{
EventWaitHandle r1 = new EventWaitHandle(false, mode);
EventWaitHandle r2 = new EventWaitHandle(false, mode);
Thread t1 = new Thread(delegate()
{
while (true)
{
r1.WaitOne();
Console.WriteLine("1");
Thread.Sleep(1000);
if (mode == EventResetMode.ManualReset) r1.Reset();
r2.Set();
}
}
);
Thread t2 = new Thread(delegate()
{
while (true)
{
r2.WaitOne();
Console.WriteLine("2");
if (mode == EventResetMode.ManualReset) r2.Reset();
r1.Set();
}
}
);
t1.Start();
t2.Start();
r1.Set();
}
static void Main()
{
EventWaitHandleTest(EventResetMode.AutoReset);
Console.WriteLine("Press any key to exit...");
Console.ReadKey(true);
}
}
}
我们为什么要用2个同步对象呢?试想如果用一个的话在执行完 t1 的循环体 r1.Set(); 代码时,CPU 分配给 t1 的时间片断可能还没有超时,那么自然不会把执行权交给 t2,因为会继续执行 t1 的循环体代码,因此用 2 个则可以避免这种问题。