在線程內核對象的內部有一個值,用于指明線程的暫停計數。當調用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函數時,就創建了線程的內核對象,并且它的暫停計數被初始化為1。當線程的暫停計數是0的時候,除非線程正在等待其他某種事情的發生,否則該線程就處于可調度狀態。
恢復線程,可以用將調用R e s u m e T h r e a d
并將C r e a t e T h r e a d函數時返回的線程句柄傳遞給它(或者是將傳遞給C r e a t e P r o c e s s的p p i P r o c I n f o參數指向的線程句柄傳遞給它):DWORD ResumeThread(HANDLE hThread);
當創建線程時,除了使用C R E AT E _ S U S P E N D E D外,也可以調用S u s p e n dT h r e a d函數來暫停線程的運行:
DWORD SuspendThread(HANDLE hThread);
暫停和恢復進程的運行
對于Wi n d o w s來說,不存在暫停或恢復進程的概念,因為進程從來不會被安排獲得C P U時間。Wi n d o w s確實允許一個進程暫停另一個進程中的所有線程的運行,但是從事暫停操作的進程必須是個調試程序。特別是,進程必須調用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之類的函數。
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);
???}
}
以上是作者實現的,但是有的時候會出錯.
?睡眠方式線程也能告訴系統,它不想在某個時間段內被調度。這是通過調用S l e e p函數來實現的:
VOID Sleep(DWORD dwMilliseconds);
關于S l e e p函數,有下面幾個重要問題值得注意:
? 調用S l e e p,可使線程自愿放棄它剩余的時間片。
? 系統將在大約的指定毫秒數內使線程不可調度。不錯,如果告訴系統,想睡眠1 0 0 m s,那么可以睡眠大約這么長時間,但是也可能睡眠數秒鐘或者數分鐘。記住, Wi n d o w s不是個實時操作系統。雖然線程可能在規定的時間被喚醒,但是它能否做到,取決于系統中還有什么操作正在進行。
? 可以調用S l e e p,并且為d w M i l l i s e c o n d s參數傳遞I N F I N I T E。這將告訴系統永遠不要調度該線程。這不是一件值得去做的事情。最好是讓線程退出,并還原它的堆棧和內核對象。
? 可以將0傳遞給S l e e p。這將告訴系統,調用線程將釋放剩余的時間片,并迫使系統調度另一個線程。但是,系統可以對剛剛調用S l e e p的線程重新調度。如果不存在多個擁有相同優先級的可調度線程,就會出現這種情況。
轉換到另一個線程系統提供了一個稱為S w i t c h To T h r e a d的函數,使得另一個可調度線程(如果存在能夠運行):
當調用這個函數的時候,系統要查看是否存在一個迫切需要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就對該線程進行調度(該線程的優先級可能低于調用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;

這個代碼做了一個簡單的假設:即它不會被中斷。但是,在搶占式操作系統中,永遠無法知道線程何時被賦予C P U時間。
幸運的是,Wi n d o w s提供了一個稱為G e t T h r e a d Ti m e s的函數,它能返回這些信息:
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的函數,適用于進程中的所有線程:
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確實提供了一些高分辨率性能函數:
BOOL QueryPerformanceFrequency(
LARGE_INTEGER* pliFrequency);
BOOL QueryPerformanceCounter(
LARGE_INTEGER* pliCount);
雖然這些函數認為,正在執行的線程并沒有得到搶占的機會,但是高分辨率的配置文件是為短期存在的代碼塊設置的。為了使這些函數運行起來更加容易一些,我創建了下面這個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.

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