一直對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的幾個方法有了直觀的瞭解, 接下來有時間再測試他們在線程同步中的使用。