多執行緒中的ManualResetEvent

iDotNetSpace發表於2009-11-26

先來看一下簡單的多執行緒控制檯程式:

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gtusing System;
using System.Threading;

namespace ManualResetEventStudy
{

    
class ThreadClass
    {
        
static void t1()
        {
            
for (int x = 1; x <= 5; x++)
            {
                Thread.Sleep(
500);
                Console.WriteLine(
"t1的x:" + x);
            }
        }

        
static void t2()
        {
            
for (int x = 1; x <= 5; x++)
            {
                Thread.Sleep(
500);
                Console.WriteLine(
"t2的x:" + x);
            }
        }

        
static void Main(string[] args)
        {
            Thread thrd1 
= new Thread(t1);
            thrd1.Start();

            Thread thrd2 
= new Thread(t2);
            thrd2.Start();


            
for (int x = 1; x <= 5; x++)
            {
                Thread.Sleep(
500);
                Console.WriteLine(
"主執行緒中的x:" + x);
            }

            Console.Read();
        }       
    }
}

 入口方法Main裡,建立了二個執行緒,分別呼叫方法t1與t2,再加上主執行緒本身,一併有三個執行緒,執行後,三個執行緒都在計數輸出,結果類似如下:

t2的x:1
t1的x:1
主執行緒中的x:1
t2的x:2
t1的x:2
主執行緒中的x:2
t2的x:3
t1的x:3
主執行緒中的x:3
t2的x:4
t1的x:4
主執行緒中的x:4
t2的x:5
t1的x:5
主執行緒中的x:5

 

三個執行緒的順序,在這段程式碼中我們是無法控制的,天知道誰先開始/誰先結束,反正都是"並行"處理,完全看CPU當時的心情  :)

問題:如果需求有變化,比如要求在主執行緒執行到某個特定的位置(或時間點)時,才讓其它執行緒開始介入,該怎麼做呢?(這種情況實際中很常見,比如某一項計算的入口引數依賴於另一項計算的結果,再比如我們計算月工資前,得先統計出員工當月考勤情況)

System.Threading名稱空間下有一個ManualResetEvent類,可以做到這一點:

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gtusing System;
using System.Threading;

namespace ManualResetEventStudy
{

    
class ThreadClass
    {       

        
static ManualResetEvent mre = new ManualResetEvent(false);

        
static void t1()
        {
            
mre.WaitOne(1000);//等待1秒後,自行啟動
            for (int x = 1; x <= 5; x++)
            {
                Thread.Sleep(
500);
                Console.WriteLine(
"t1的x:" + x);
            }
        }

        
static void t2()
        {
            
mre.WaitOne();//一直等待下去,直到有"人"呼叫mre.set()發出訊號為止
            for (int x = 1; x <= 5; x++)
            {
                Thread.Sleep(
500);
                Console.WriteLine(
"t2的x:" + x);
            }
        }

        
static void Main(string[] args)
        {
            Thread thrd1 
= new Thread(t1);
            thrd1.Start();

            Thread thrd2 
= new Thread(t2);
            thrd2.Start();


            
for (int x = 1; x <= 5; x++)
            {
                Thread.Sleep(
500);
                Console.WriteLine(
"主執行緒中的x:" + x);

                if (x == 3
                {
                    mre.Set();//通知所有等待的執行緒:“同志們,可以動啦”:)
                }
            }

            Console.Read();
        }        

    }
}

 t1方法中,我們用 mre.WaitOne(1000);讓呼叫該方法的執行緒先等候1秒,t2方法中,我們用mre.WaitOne()無限等候,然後主執行緒中計數到3的時候,手動呼叫mre.Set()方法喚醒所有等候中的執行緒,執行結果類似下面這樣:

主執行緒中的x:1
主執行緒中的x:2
t1的x:1
主執行緒中的x:3
t1的x:2
t2的x:1
主執行緒中的x:4
t1的x:3
主執行緒中的x:5
t2的x:2
t1的x:4
t2的x:3
t1的x:5
t2的x:4
t2的x:5

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-620626/,如需轉載,請註明出處,否則將追究法律責任。

相關文章