線上程核心對象的內部有一個用於指明線程的掛起計數的值。當調用CreateProcess或CreateThread函數時,就建立了線程的核心對象,並且它的掛起計數被初始化為1。這可以防止線程被調度到CPU中。原因是因為線程的初始化需要時間,希望在系統做好充分的準備之後再開始執行線程。
當線程完全初始化好了之後, CreateProcess或CreateThread要查看是否已經傳遞了CRE ATE_ SUSPENDED標誌。如果已經傳遞了這個標誌,那麼這些函數就返回,同時新線程處於掛起狀態。如果尚未傳遞該標誌,那麼該函數將線程的暫停計數遞減為0。當線程的暫停計數是0的時候,除非線程正在等待其他某種事情的發生,否則該線程就處於可調度狀態。
建立一個掛起狀態的線程,就能夠線上程有機會執行任何代碼之前改變線程的運行環境(如優先順序)。一旦改變了線程的環境,必須使線程成為可調度線程。要進行這項操作,可以調用Resum eThread,將調用CreateThread函數時返回的線程控制代碼傳遞給它(或者是將傳遞給CreateProce ss的ppiProcInfo參數指向的線程控制代碼傳遞給它):
DWORD ResumeThread(HANDLEhThread);
如果Resum eThread 函數運行成功,它將返回線程的前一個掛起計數,否則返回0xFFFFFFFF。
單個線程可以暫停若干次。如果一個線程暫停了3次,它必須恢複3次,然後它才可以被分配給一個CPU。當建立線程時,除了使用CREATE_SUSPENDED外,也可以調用SuspendThread函數來暫停線程的運行:
DWORD SuspendThread(HANDLEhThread);
任何線程都可以調用該函數來暫停另一個線程的運行(只要擁有線程的控制代碼)。線程可以自行暫停運行,但是不能自行恢複運行。注意, SuspendThread與核心方式的執行是非同步進行的,但是線上程恢複運行之前,不會發生使用者方式的執行。
注意:在實際環境中,調用SuspendThread時必須小心,因為不知道掛起線程運行時它在進行什麼操作。如果線程試圖從堆棧中分配記憶體,那麼該線程將在該堆棧上設定一個鎖。當其他線程試圖訪問該堆棧時,這些線程的訪問就被停止,直到第一個線程恢複運行。只有確切知道目標線程是什麼(或者目標線程正在做什麼),並且採取強有力的措施來避免因掛起線程的運行而帶來的問題或死結狀態,SuspendThread才是安全的。(FangSH註: 必須知道要被掛起的線程在做什麼事。不然有可能會造成死結或其他問題)
FangSH 2010-12-28