今天詳細說一下ManualResetEvent
它可以通知一個或多個正在等待的線程已發生事件,允許線程通過發信號互相通信,來控制線程是否可心訪問資源
當一個線程開始一個活動(此活動必須完成后,其他線程才能開始)時,它調用 Reset 以將 ManualResetEvent 置於非終止狀態。此線程可被視為控制 ManualResetEvent。調用 ManualResetEvent 上的 WaitOne 的線程將阻止,並等待信號。當控制線程完成活動時,它調用 Set 以發出等待線程可以繼續進行的信號。並釋放所有等待線程。
一旦它被終止,ManualResetEvent 將保持終止狀態,直到它被手動重置。即對 WaitOne 的調用將立即返回。
上面是它的功能描述,你可能會有點暈。我會用代碼一點一點解釋它,看完我寫的這些內容,你自己運行一下代碼你就會明白它的功能
我們從初始化來開始講
可以通過將布爾值傳遞給構造函數來控制 ManualResetEvent 的初始狀態,如果初始狀態處於終止狀態,為 true;否則為 false。
我用代碼 讓大家看一下什么是終止狀態和非終止狀態
先看一下代碼
class Program
{
static ManualResetEvent _mre = new ManualResetEvent(false);
static void Main(string[] args)
{
Thread[] _threads = new Thread[3];
for (int i = 0; i < _threads.Count(); i++)
{
_threads[i] = new Thread(ThreadRun);
_threads[i].Start();
}
}
static void ThreadRun()
{
int _threadID = 0;
while (true)
{
_mre.WaitOne();
_threadID = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("current Tread is " + _threadID);
Thread.Sleep(TimeSpan.FromSeconds(2));
}
}
}
當初始化為true時,為終止狀態
static ManualResetEvent _mre = new ManualResetEvent(true);
執行結果

當初始化為false時,為非終止狀態
static ManualResetEvent _mre = new ManualResetEvent(false);
執行結果為

這樣我們就能看出來
終止狀態時WaitOne()允許線程訪問下邊的語句
非終止狀態時WaitOne()阻塞線程,不允許線程訪問下邊的語句
我們也可以把WaitOne()放在方法最下邊
static void ThreadRun()
{
int _threadID = 0;
while (true)
{
_threadID = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("current Tread is " + _threadID);
Thread.Sleep(TimeSpan.FromSeconds(2));
_mre.WaitOne();
}
}
當初始化為true時執行結果和上邊的一樣會不停的執行

初始化為false時執行到waitOne()時就阻塞線程不會再往下執行了

接下來你可能就會想當在非終止狀態時怎么讓線程繼續執行,怎么再讓它停下來,這就要用了set()和Reset()方法了
把非終止狀態改為終止狀態用Set()方法
把終止狀態改為非終止狀態用Reset()方法
我用用代碼來實現它們只要把我們上 邊的代碼做一下改動
class Program
{
static ManualResetEvent _mre = new ManualResetEvent(false);
static void Main(string[] args)
{
Console.WriteLine("輸入1為Set() 開始運行");
Console.WriteLine("輸入2為Reset() 暫停運行");
Thread[] _threads = new Thread[3];
for (int i = 0; i < _threads.Count(); i++)
{
_threads[i] = new Thread(ThreadRun);
_threads[i].Start();
}
while (true)
{
switch (Console.ReadLine())
{
case "1":
_mre.Set();
Console.WriteLine("開始運行");
break;
case "2":
_mre.Reset();
Console.WriteLine("暫停運行");
break;
default:
break;
}
}
}
static void ThreadRun()
{
int _threadID = 0;
while (true)
{
_threadID = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("current Tread is " + _threadID);
Thread.Sleep(TimeSpan.FromSeconds(2));
_mre.WaitOne();
}
}
}
當輸入1 時會調用 Set()方法 ManualResetEvent 處於終止狀態會WaitOne不會阻塞線程會一直運行下去
當輸入2時會調用 Reser()方法ManualResetEvent處於非終止狀態WaitOne會阻塞線程直到再調用 Set()方法
看一下執行結果吧

