C#2010: 執行緒的暫停和重啟(Auto/Manual ResetEvent)-以計時器為例
在C#2010版以前, 執行緒可以使用Suspend( ) 和 Resume( ) 等方法來暫停執行緒和重啟被暫停中的執行緒, 來到C#2010版 Suspend( ) 和 Resume( ) 被認為是過時的語法, 即便不使用Suspend( ) 和 Resume( ), 仍然有其它方法可以達到執行緒的暫停和重啟, 也是本篇要討論的.
要讓程式暫停在某行程式碼, 直到再次下達指令才繼續執行, 我們必須借助
AutoResetEvent 或 ManualResetEvent, AutoResetEvent 和 MannualResetEvent 的主要差異有二:
一、
AutoResetEvent 和MannualResetEvent 有一個叫WaitOne 的方法, 可以將緒行緒hand住, 使用 Set 方法可讓被hand在WaitOne的執行緒繼續往下執行.
在宣告 AutoResetEvent 和 MannualResetEvent 同時必須給定一個 bool 起始參數值, 如:
AutoResetEvent TestTdEvent = new AutoResetEvent(false);
ManualResetEvent MTestTdEvent = new ManualResetEvent(false);
false 表示程式遇到 WaitOne 方法時會被 hand 住. 反之則否.
AutoResetEvent 的起始值設 true, 一旦經過 WaitOne 之後就會被自動改成 false, 當第二次來到 WaitOne 的時就會被 hand 住, 而 MannualResetEvent 一旦被設為 true 就會一直保持 true 的狀態, 必須使用 Reset 方法, 才能將起始值改成 false.
二、
若有多個執行緒被 hand 在 WaitOne 上, AutoResetEvent 使用 Set 方法只能啟動某一個執行緒, 若有 n 個執行緒被 hand 在 WaitOne 上, AutoResetEvent就要 Set n 次才可以讓所有執行緒繼續執行. 而 MannualResetEvent 可以同時重啟所有被 hand 在 WaitOne的執行緒.
AutoResetEvent:
===================================================================================
// 先行宣告必要的變數
Thread TestTd; // 宣告執行緒
bool FlagStop = false; // 做為計時器的開關
AutoResetEvent TestTdEvent = new AutoResetEvent(false);
int Cumtm=0;
// 啟動執行緒
private void StartTestTd()
{
TestTd = new Thread(TestProc);
TestTd.Start();
}
// 執行緒主要是每秒顯示一次系統的時間, 當 FlagStop 被設為true時則進入 WaitOne
private void TestProc()
{
while (true)
{
if (FlagStop == true)
{
TestTdEvent.WaitOne();
}
else
{
Thread.Sleep(1000);
Cumtm += 1;
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss") + ", Cumtm = " + Cumtm);
}
}
}
// 記時器開關.
private void btmOnOff_Click(object sender, EventArgs e)
{
FlagStop = !FlagStop;
if (FlagStop == false) TestTdEvent.Set();
}
===================================================================================
MannualResetEvent:
===================================================================================
// 先行宣告必要的變數
Thread MTestTd; // 宣告執行緒
bool FlagStop = false; // 做為計時器的開關
ManualResetEvent MTestTdEvent = new ManualResetEvent(true);
int Cumtm=0;
// 啟動執行緒
private void StartTestTd()
{
MTestTd = new Thread(MTestProc);
MTestTd.Start();
}
// 執行緒主要是每秒顯示一次系統的時間, 這裡因 MannualResetEvent 的bool起始值不會自動被設為false, 因此在這裡不用像AutoResetEvent判斷計時器是否要終止. bool起始值本身就可以拿來當執行緒的開關.
private void MTestProc()
{
while (true)
{
MTestTdEvent.WaitOne();
Thread.Sleep(1000);
Cumtm += 1;
Console.WriteLine(DateTime.Now.ToString("HH:mm:ss") + ", Cumtm = " + Cumtm);
}
}
// 記時器開關.
private void btmOnOff_Click(object sender, EventArgs e)
{
FlagStop = !FlagStop;
if (FlagStop == true)
{
MTestTdEvent.Reset();
}
else
{
MTestTdEvent.Set();
}
}
===================================================================================
這裡只有做計時器的範例, 至於要檢驗多個執行緒暫停重啟的部份, 只要再多加一個計時器便可明白, 這裡就不多做說明囉~ :)