一直对ManualResetEvent的用法不是很明白,今天决定写些小程序,测试一下,直观感受它的用法。
MSDN的解释: 通知一个或多个正在等待的线程已发生事件。 此类不能被继承。
Part1:初始化
// 初始化一个ManualResetEvent实例
private static ManualResetEvent _mer = new ManualResetEvent(false);
可见,初始化时接受一个bool值,它是有什么作用呢?
MSND的解释:用一个指示是否将初始状态设置为终止的布尔值初始化 ManualResetEvent类的新实例。即:可以通过将布尔值传递给构造函数来控制 ManualResetEvent 的初始状态,如果初始状态处于终止状态,为 true;否则为 false。
用程序来直观感受一下:
static void Main(string[] args)
{
Console.WriteLine("Enter Main" + Thread.CurrentThread.Name);
for (int id = 0; id < 2; id++)
{
Thread th = new Thread(new ThreadStart(ThreadProc));
th.Name = "thread_" + id.ToString();
th.Start();
}
}
private static void ThreadProc()
{
Console.WriteLine("Enter ThreadProc" + Thread.CurrentThread.Name);
Console.WriteLine("before WaitOne " + Thread.CurrentThread.Name);
_mer.WaitOne();
Console.WriteLine("after WaitOne " + Thread.CurrentThread.Name);
Console.WriteLine("Exit ThreadProc" + Thread.CurrentThread.Name);
}
测试结果:
先加个解释,ThreadProc里用到了WaitOne(), MSDN的解释是:阻止当前线程,直到当前 WaitHandle 收到信号。 (继承自WaitHandle。)
回到初始化,初始化为false,即_mer是非终止状态,这里我想加个自己的理解,非终止状态就是工作状态,就是说_mer是起作用的,从程序的结果可以看到,
程序停在了_mer.WaitOne(); 这一句,没有输出Console.WriteLine("after WaitOne " + Thread.CurrentThread.Name);这句,就是说_mer起作用了。
如果初始化时是true,即终止状态,就是非工作状态,程序执行的结果就是执行完毕,闪退。
总结: 初始化为true,终止状态,即不起作用状态;初始化为false,非终止状态,即起作用状态。
Part2:Set与Reset
ManualResetEvent.Set() MSDN的解释:将事件状态设置为终止状态,允许一个或多个等待线程继续。 (继承自EventWaitHandle。)
也就是将ManualResetEvent实例设置为不起作用状态。
程序测试:
_mer初始化还是false,Main() 方法里加了一句: _mer.Set();
static void Main(string[] args)
{
Console.WriteLine("Enter Main" + Thread.CurrentThread.Name);
_mer.Set();
for (int id = 0; id < 2; id++)
{
Thread th = new Thread(new ThreadStart(ThreadProc));
th.Name = "thread_" + id.ToString();
th.Start();
}
}
执行结果:执行完毕,闪退。即: _mer.WaitOne(); 不起作用。
ManualResetEvent.Reset() MSDN解释:将事件状态设置为非终止状态,导致线程阻止。
即设置为起作用状态。
程序测试:
初始化一个为true的实例,Main()方法里加了一句:_mer.Reset();
static void Main(string[] args)
{
Console.WriteLine("Enter Main" + Thread.CurrentThread.Name);
_mer.Reset();
for (int id = 0; id < 2; id++)
{
Thread th = new Thread(new ThreadStart(ThreadProc));
th.Name = "thread_" + id.ToString();
th.Start();
}
}
执行结果:
可见, 初始化为true,终止状态(不起作用状态),Reset()后,就为非终止状态(起作用状态)。
Part3 : WaitOne(Int32)
MSDN的解释:阻止当前线程,直到当前 WaitHandle 收到信号,同时使用 32 位带符号整数指定时间间隔(以毫秒为单位)
private static void ThreadProc()
{
Console.WriteLine("Enter ThreadProc" + Thread.CurrentThread.Name);
Console.WriteLine("before WaitOne " + Thread.CurrentThread.Name);
_mer.WaitOne(5000);
Console.WriteLine("after WaitOne " + Thread.CurrentThread.Name);
Console.WriteLine("Exit ThreadProc" + Thread.CurrentThread.Name);
Console.Read();
}
程序中有一句:
_mer.WaitOne(5000);
阻塞5秒钟,程序执行完毕。
如果在Main方法里加上这两句:
Thread.Sleep(2000);
_mer.Set();
<pre name="code" class="csharp">static void Main(string[] args)
{
Console.WriteLine("Enter Main" + Thread.CurrentThread.Name);
for (int id = 0; id < 2; id++)
{
Thread th = new Thread(new ThreadStart(ThreadProc));
th.Name = "thread_" + id.ToString();
th.Start();
}
Thread.Sleep(2000);
_mer.Set();
}
程序执行情况是: ThreadProc阻塞,2秒钟接收到Set()信号, 执行WaitOne(5000)后面的语句,即只阻塞了两秒。
今天是对ManualResetEvent的几个方法有了直观的了解, 接下来有时间再测试他们在线程同步中的使用。