• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            C++ Programmer's Cookbook

            {C++ 基礎} {C++ 高級} {C#界面,C++核心算法} {設計模式} {C#基礎}

            windows核心編程--線程高級

            暫停和恢復線程的運行

            在線程內核對象的內部有一個值,用于指明線程的暫停計數。當調用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的函數,使得另一個可調度線程(如果存在能夠運行):

            BOOL SwitchToThread();

            當調用這個函數的時候,系統要查看是否存在一個迫切需要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)


            Windows 2000實際上允許用戶對這種調整進行相應的配置。在System Properties(系統屬性)對話框的A d v a n c e d選項卡上,用戶可以單擊Performance Options(性能選項)按鈕

            posted on 2006-09-14 10:13 夢在天涯 閱讀(2278) 評論(0)  編輯 收藏 引用 所屬分類: Windows API

            公告

            EMail:itech001#126.com

            導航

            統計

            • 隨筆 - 461
            • 文章 - 4
            • 評論 - 746
            • 引用 - 0

            常用鏈接

            隨筆分類

            隨筆檔案

            收藏夾

            Blogs

            c#(csharp)

            C++(cpp)

            Enlish

            Forums(bbs)

            My self

            Often go

            Useful Webs

            Xml/Uml/html

            搜索

            •  

            積分與排名

            • 積分 - 1804603
            • 排名 - 5

            最新評論

            閱讀排行榜

            国产午夜精品久久久久九九电影 | 国产激情久久久久影院老熟女| 久久精品国产亚洲av麻豆色欲 | 伊人久久国产免费观看视频| 亚洲欧洲精品成人久久曰影片 | 亚洲午夜久久久久久久久电影网| 狠狠色丁香久久婷婷综合| 久久久国产精品亚洲一区| 国产成人精品久久亚洲高清不卡 国产成人精品久久亚洲高清不卡 国产成人精品久久亚洲 | 国产精品九九久久精品女同亚洲欧美日韩综合区| 狠狠久久亚洲欧美专区| 久久精品无码一区二区日韩AV| 超级碰碰碰碰97久久久久| 久久精品无码午夜福利理论片| 很黄很污的网站久久mimi色| 色偷偷久久一区二区三区| 久久精品国产99国产精品| 狠狠狠色丁香婷婷综合久久五月| 日本WV一本一道久久香蕉| 国产精品久久久久乳精品爆| 99国产精品久久| 亚洲人成网站999久久久综合| 精品午夜久久福利大片| 欧美午夜精品久久久久免费视| 亚洲国产成人精品女人久久久 | 久久亚洲私人国产精品vA| 久久精品中文字幕第23页| 久久综合综合久久97色| 亚洲va中文字幕无码久久不卡| 久久伊人中文无码| 国产精品99久久久久久猫咪| 国产V亚洲V天堂无码久久久| 亚洲成色WWW久久网站| 久久国产色av免费看| 波多野结衣久久一区二区| 尹人香蕉久久99天天拍| 亚洲欧美成人久久综合中文网| 日韩久久久久中文字幕人妻| 久久久久久国产a免费观看不卡| 国产香蕉97碰碰久久人人| 国产免费久久精品99久久|