在線程內(nèi)核對象的內(nèi)部有一個值,用于指明線程的暫停計數(shù)。當(dāng)調(diào)用C r e a t e P r o c e s s或C r e a t e T h r e a d函數(shù)時,就創(chuàng)建了線程的內(nèi)核對象,并且它的暫停計數(shù)被初始化為1。當(dāng)線程的暫停計數(shù)是0的時候,除非線程正在等待其他某種事情的發(fā)生,否則該線程就處于可調(diào)度狀態(tài)。
恢復(fù)線程,可以用將調(diào)用R e s u m e T h r e a d
并將C r e a t e T h r e a d函數(shù)時返回的線程句柄傳遞給它(或者是將傳遞給C r e a t e P r o c e s s的p p i P r o c I n f o參數(shù)指向的線程句柄傳遞給它):DWORD ResumeThread(HANDLE hThread);
當(dāng)創(chuàng)建線程時,除了使用C R E AT E _ S U S P E N D E D外,也可以調(diào)用S u s p e n dT h r e a d函數(shù)來暫停線程的運行:
DWORD SuspendThread(HANDLE hThread);
暫停和恢復(fù)進(jìn)程的運行
對于Wi n d o w s來說,不存在暫停或恢復(fù)進(jìn)程的概念,因為進(jìn)程從來不會被安排獲得C P U時間。Wi n d o w s確實允許一個進(jìn)程暫停另一個進(jìn)程中的所有線程的運行,但是從事暫停操作的進(jìn)程必須是個調(diào)試程序。特別是,進(jìn)程必須調(diào)用Wa i t F o r D e b u g E v e n t和C o n t i n u e D e b u g E v e n t之類的函數(shù)。
VOID?SuspendProcess(DWORD?dwProcessID,?BOOL?fSuspend)


{
???//Get?the?list?of?threads?in?the?system.
???HANDLE?hSnapshot?=?CreateToolhelp32Snapshot(
??????TH32CS_SNAPTHREAD,?dwProcessID);

???if(hSnapshot?!=?INVALID_HANDLE_VALUE)?

???
{
??????//Walk?the?list?of?threads.

??????THREADENTRY32?te?=?
{?sizeof(te)?};
??????BOOL?fOk?=?Thread32First(hSnapshot,?&te);

??????for(;?fOk;?fOk?=?Thread32Next(hSnapshot,?&te))?

??????
{
?????????//Is?this?thread?in?the?desired?process?
?????????if(te.th32OwnerProcessID?==?dwProcessID)?

?????????
{
????????????//Attempt?to?convert?the?thread?ID?into?a?handle.
????????????HANDLE?hThread?=?OpenThread(THREAD_SUSPEND_RESUME,
???????????????FALSE,?te.th32ThreadID);

????????????if(hThread?!=?NULL)?

????????????
{
???????????????//Suspend?or?resume?the?thread.
???????????????if(fSuspend)
??????????????????SuspendThread(hThread);
???????????????else
??????????????????ResumeThread(hThread);
????????????}
????????????CloseHandle(hThread);
?????????}
??????}
??????CloseHandle(hSnapshot);
???}
}
以上是作者實現(xiàn)的,但是有的時候會出錯.
?睡眠方式線程也能告訴系統(tǒng),它不想在某個時間段內(nèi)被調(diào)度。這是通過調(diào)用S l e e p函數(shù)來實現(xiàn)的:
VOID Sleep(DWORD dwMilliseconds);
關(guān)于S l e e p函數(shù),有下面幾個重要問題值得注意:
? 調(diào)用S l e e p,可使線程自愿放棄它剩余的時間片。
? 系統(tǒng)將在大約的指定毫秒數(shù)內(nèi)使線程不可調(diào)度。不錯,如果告訴系統(tǒng),想睡眠1 0 0 m s,那么可以睡眠大約這么長時間,但是也可能睡眠數(shù)秒鐘或者數(shù)分鐘。記住, Wi n d o w s不是個實時操作系統(tǒng)。雖然線程可能在規(guī)定的時間被喚醒,但是它能否做到,取決于系統(tǒng)中還有什么操作正在進(jìn)行。
? 可以調(diào)用S l e e p,并且為d w M i l l i s e c o n d s參數(shù)傳遞I N F I N I T E。這將告訴系統(tǒng)永遠(yuǎn)不要調(diào)度該線程。這不是一件值得去做的事情。最好是讓線程退出,并還原它的堆棧和內(nèi)核對象。
? 可以將0傳遞給S l e e p。這將告訴系統(tǒng),調(diào)用線程將釋放剩余的時間片,并迫使系統(tǒng)調(diào)度另一個線程。但是,系統(tǒng)可以對剛剛調(diào)用S l e e p的線程重新調(diào)度。如果不存在多個擁有相同優(yōu)先級的可調(diào)度線程,就會出現(xiàn)這種情況。
轉(zhuǎn)換到另一個線程系統(tǒng)提供了一個稱為S w i t c h To T h r e a d的函數(shù),使得另一個可調(diào)度線程(如果存在能夠運行):
當(dāng)調(diào)用這個函數(shù)的時候,系統(tǒng)要查看是否存在一個迫切需要C P U時間的線程。如果沒有線程迫切需要C P U時間,S w i t c h To T h r e a d就會立即返回。如果存在一個迫切需要C P U時間的線程,S w i t c h To T h r e a d就對該線程進(jìn)行調(diào)度(該線程的優(yōu)先級可能低于調(diào)用S w i t c h To T h r e a d的線程)。
線程的運行時間
//Get?the?current?time?(start?time).
DWORD?dwStartTime?=?GetTickCount();

//Perform?complex?algorithm?here.

//Subtract?start?time?from?current?time?to?get?duration.
DWORD?dwElapsedTime?=?GetTickCount()?-?dwStartTime;

這個代碼做了一個簡單的假設(shè):即它不會被中斷。但是,在搶占式操作系統(tǒng)中,永遠(yuǎn)無法知道線程何時被賦予C P U時間。
幸運的是,Wi n d o w s提供了一個稱為G e t T h r e a d Ti m e s的函數(shù),它能返回這些信息:
BOOL GetThreadTimes(HANDLE hThread,
PFILETIME pftCreationTime, PFILETIME pftExitTime,
PFILETIME pftKernelTime, PFILETIME pftUserTime);
使用實例
__int64?FileTimeToQuadWord(PFILETIME?pft)?


{
???return?(Int64ShllMod32(
??????pft->dwHighDateTime,?32)?|?pft->dwLowDateTime);
}

void?PerformLongOperation()?


{
???FILETIME?ftKernelTimeStart,?ftKernelTimeEnd;
???FILETIME?ftUserTimeStart,???ftUserTimeEnd;

???FILETIME?ftDummy;
???__int64?qwKernelTimeElapsed,?qwUserTimeElapsed,
??????qwTotalTimeElapsed;

???//Get?starting?times.
???GetThreadTimes(GetCurrentThread(),?&ftDummy,
??????&ftDummy,?&ftKernelTimeStart,?&ftUserTimeStart);

???//Perform?complex?algorithm?here.

???//Get?ending?times.
???GetThreadTimes(GetCurrentThread(),?&ftDummy,
??????&ftDummy,?&ftKernelTimeEnd,?&ftUserTimeEnd);

???//Get?the?elapsed?kernel?and?user?times?by?
???//converting?the?start?and?end?times?
???//from?FILETIMEs?to?quad?words,?and?then?
???//subtract?the?start?times?from?the?end?times.

???qwKernelTimeElapsed?=?
??????FileTimeToQuadWord(&ftKernelTimeEnd)?-
??????FileTimeToQuadWord(&ftKernelTimeStart);

???qwUserTimeElapsed?=?
??????FileTimeToQuadWord(&ftUserTimeEnd)?-
??????FileTimeToQuadWord(&ftUserTimeStart);

???//Get?total?time?duration?by?adding?the?kernel
???//and?user?times.

???qwTotalTimeElapsed?=?qwKernelTimeElapsed?+?
??????qwUserTimeElapsed;

???//The?total?elapsed?time?is?in?
???//qwTotalTimeElapsed.
}

注意,G e t P r o c e s s Ti m e s是個類似G e t T h r e a d Ti m e s的函數(shù),適用于進(jìn)程中的所有線程:
BOOL GetProcessTimes(HANDLE hProcess,
PFILETIME pftCreationTime, PFILETIME pftExitTime,
PFILETIME pftKernelTime, PFILETIME pftUserTime);
對于高分辨率的配置文件來說, G e t T h r e a d Ti m e s并不完美。Wi n d o w s確實提供了一些高分辨率性能函數(shù):
BOOL QueryPerformanceFrequency(
LARGE_INTEGER* pliFrequency);
BOOL QueryPerformanceCounter(
LARGE_INTEGER* pliCount);
雖然這些函數(shù)認(rèn)為,正在執(zhí)行的線程并沒有得到搶占的機(jī)會,但是高分辨率的配置文件是為短期存在的代碼塊設(shè)置的。為了使這些函數(shù)運行起來更加容易一些,我創(chuàng)建了下面這個C + +類:
class?CStopwatch?


{
public:
???CStopwatch()?

???
{?
??????QueryPerformanceFrequency(&m_liPerfFreq);
??????Start();
???}

???void?Start()?

???
{?
??????QueryPerformanceCounter(&m_liPerfStart);
???}

???__int64?Now()?const?

???
{
??????//Returns?#?of?milliseconds?since
??????//Start?was?called

??????LARGE_INTEGER?liPerfNow;
??????QueryPerformanceCounter(&liPerfNow);

??????return?(((liPerfNow.QuadPart?-?
?????????m_liPerfStart.QuadPart)?*?1000)/
?????????m_liPerfFreq.QuadPart);
???}

private:

???//Counts?per?second
???LARGE_INTEGER?m_liPerfFreq;???

???//Starting?count
???LARGE_INTEGER?m_liPerfStart;??
};

使用這個類如下:(這樣的封裝類很多的,我的blog有介紹)
//Create?a?stopwatch?timer
//(which?defaults?to?the?current?time).
CStopwatch?stopwatch;

//Execute?the?code?I?want?to?profile?here.

//Get?how?much?time?has?elapsed?up?to?now.
??__int64?qwElapsedTime?=?stopwatch.Now();

//qwElapsedTime?indicates?how?long?
//the?profiled?code?executed?in?milliseconds.

運用結(jié)構(gòu)環(huán)境(跟cpu的類型有關(guān)系)
環(huán)境結(jié)構(gòu)使得系統(tǒng)能夠記住線程的狀態(tài),這樣,當(dāng)下次線程擁有可以運行的C P U時,它就能夠找到它上次中斷運行的地方。
Wi n d o w s實際上允許查看線程內(nèi)核對象的內(nèi)部情況,以便抓取它當(dāng)前的一組C P U寄存器。若要進(jìn)行這項操作,只需要調(diào)用G e t T h r e a d C o n t e x t函數(shù):
BOOL GetThreadContext(HANDLE hThread,
PCONTEXT pContext);
Wi n d o w s使你能夠修改C O N T E X T結(jié)構(gòu)中的成員,然后通過調(diào)用S e t T h r e a d C o n t e x t將新寄存器值放回線程的內(nèi)核對象中:
BOOL SetThreadContext(HANDLE hThread,
CONST CONTEXT *pContext);
線程的優(yōu)先級
若要設(shè)置和獲得線程的相對優(yōu)先級,必須調(diào)用下面的這些函數(shù):
BOOL SetThreadPriority(HANDLE hThread,
int nPriority);
下面是檢索線程的相對優(yōu)先級的補(bǔ)充函數(shù):
int GetThreadPriority(HANDLE hThread);
程序的優(yōu)先級(進(jìn)程的優(yōu)先級)
下面是如何使一個進(jìn)程將它自己的優(yōu)先級類設(shè)置為空閑的例子:
BOOL SetPriorityClass(GetCurrentProcess(),
IDLE_PRIORITY_CLASS);
下面是用來檢索進(jìn)程的優(yōu)先級類的補(bǔ)充函數(shù):
DWORD GetPriorityClass(HANDLE hProcess);
動態(tài)提高線程的優(yōu)先級等級
有些編程人員抱怨說,系統(tǒng)動態(tài)提高線程優(yōu)先級等級的功能對他們的線程性能會產(chǎn)生一種不良的影響,為此M i c r o s o f t增加了下面兩個函數(shù),這樣就能夠使系統(tǒng)的動態(tài)提高線程優(yōu)先級等級的功能不起作用:
BOOL SetProcessPriorityBoost(HANDLE hProcess,
BOOL DisablePriorityBoost);
BOOL SetThreadPriorityBoost(HANDLE hThread,
BOOL DisablePriorityBoost);
這兩個函數(shù)具有許多相似的共性,可以用來確定是激活還是停用優(yōu)先級提高功能:
BOOL GetProcessPriorityBoost(HANDLE hProcess,
PBOOL pDisablePriorityBoost);
BOOL GetThreadPriorityBoost(HANDLE hThread,
PBOOL pDisablePriorityBoost);
為前臺進(jìn)程調(diào)整調(diào)度程序(windows設(shè)置提供可以自定義優(yōu)先執(zhí)行application或后臺的server)