版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第16章 多任務(wù)與多線程編程,C+高級(jí)編程,本章主要教學(xué)內(nèi)容,進(jìn)程與線程 線程的種類(lèi)與MFC同步類(lèi) 線程的使用 線程的同步及常用的同步對(duì)象,第16章 多任務(wù)與多線程編程,16.1 程序、進(jìn)程和線程概述 16.2 線程的種類(lèi) 16.3 線程的創(chuàng)建、啟動(dòng)和終止 16.4 線程的操作和管理 16.5 在VC+環(huán)境中使用同步對(duì)象 16.6 本章小結(jié) 16.7 思考與練習(xí),16.1 程序、進(jìn)程和線程概述,16.1.1 多任務(wù)、進(jìn)程和線程,1Windows3.x的協(xié)同多任務(wù),如何解決后臺(tái)工作和對(duì)用戶的隨時(shí)響應(yīng)之間的協(xié)同?詳見(jiàn)教材P27。,Windows3.x對(duì)應(yīng)用程序的CPU控制權(quán)的調(diào)度方式: 協(xié)同式多任
2、務(wù)。其特點(diǎn)詳見(jiàn)教材P27。,補(bǔ)充知識(shí):什么是模態(tài)對(duì)話框和非模態(tài)對(duì)話框? 見(jiàn)附帶文件1。,16.Windows95/NT的搶先式多任務(wù),Windows95/NT對(duì)應(yīng)用程序的CPU控制權(quán)的 調(diào)度方式:搶先式多任務(wù)。其特點(diǎn)詳見(jiàn)教材P28。,16.1.1 多任務(wù)、進(jìn)程和線程,3進(jìn)程與線程,16.1.1 多任務(wù)、進(jìn)程和線程,進(jìn)程由私有虛擬地址空間、代碼、數(shù)據(jù)和其它操作系統(tǒng)資源(如進(jìn)程創(chuàng)建的文件、同步對(duì)象等)組成。,進(jìn)程就是應(yīng)用程序的運(yùn)行實(shí)例。,1)什么是進(jìn)程?,一個(gè)應(yīng)用程序可以運(yùn)行一個(gè)或多個(gè)進(jìn)程。多任務(wù)就是指操作系統(tǒng)可以同時(shí)運(yùn)行多個(gè)進(jìn)程。,16.1.1 多任務(wù)、進(jìn)程和線程,2)什么是線程?,一個(gè)線程可以
3、執(zhí)行程序的任意部分的代碼,即使這部分代碼被另一個(gè)線程并發(fā)地執(zhí)行。,線程是Windows95/NT操作系統(tǒng)分時(shí)調(diào)度中分配CPU時(shí)間的基本單位。,一個(gè)進(jìn)程可以有一個(gè)或多個(gè)線程,其中一個(gè)是主線程。,一個(gè)進(jìn)程的所有線程共享它的虛擬地址空間、全局變量和操作系統(tǒng)資源。,16.1.1 多任務(wù)、進(jìn)程和線程,3)進(jìn)程與線程的關(guān)系?,16.2 線程的種類(lèi),線程有兩種,用戶界面線程,工作者線程,MFC應(yīng)用程序通過(guò)調(diào)用AfxBeginThread函數(shù)并給定不同的參數(shù)來(lái)自動(dòng)創(chuàng)建兩種線程,而不需要程序自己創(chuàng)建, AfxBeginThread函數(shù)的具體說(shuō)明在16.3.1中。,16.16.1 MFC中的線程類(lèi),1. MFC應(yīng)
4、用程序中的線程可由對(duì)象CWinThread表示,CWinThread類(lèi)派生自CcmdTarget類(lèi);,16. CWinThread對(duì)象代表在一個(gè)應(yīng)用程序內(nèi)運(yùn)行的線程;,3. CWinThread對(duì)象允許一個(gè)應(yīng)用程序擁有多個(gè)線程;,4. CWinThread對(duì)象支持兩種線程類(lèi)型:用戶界面線程和工作者線程;,16.16.1 MFC中的線程類(lèi),5. 用戶界面線程可以由CWinThread類(lèi)派生,也可以是CWinApp類(lèi)或其派生類(lèi)。但為安全起見(jiàn),應(yīng)由CWinThread類(lèi)派生。,6. 任何使用MFC的線程必須由MFC創(chuàng)建,創(chuàng)建一個(gè)線程必須調(diào)用AfxBeginThread函數(shù)。,7. CWinThrea
5、d類(lèi)的數(shù)據(jù)成員即成員函數(shù)見(jiàn)表2-1。,16.16.2 用戶界面線程(UI),1) 用戶界面線程擁有自己的消息循環(huán)來(lái)處理界面消息,具有收發(fā)消息的功能,處理從消息隊(duì)列取得的消息;,2) 用戶界面線程通常要與用戶交互;,3) 用戶界面線程可由CWinApp類(lèi)派生(注:CWinApp類(lèi)由CWinThread類(lèi)派生),也可以由CWinThread類(lèi)直接派生。,4) 一個(gè)應(yīng)用程序的主線程通常由CWinApp類(lèi)派生,主線程應(yīng)該是用戶界面線程。,16.16.3 工作者線程,1) 工作者線程沒(méi)有自己的消息循環(huán),一般用來(lái)完成后臺(tái)的工作,如后臺(tái)計(jì)算、打印、與其它設(shè)備的串行數(shù)據(jù)通信等,這些工作的共同特點(diǎn)就是耗時(shí)。,2
6、) 為了不影響主線程與用戶的交互,通常耗時(shí)的工作交給工作者線程來(lái)完成;,3) 工作者線程可由CWinThread類(lèi)直接派生。,16.3 線程的創(chuàng)建、啟動(dòng)和終止,16.3.1 線程的創(chuàng)建,線程的創(chuàng)建由AfxBeginThread函數(shù)完成。,AfxBeginThread函數(shù)有兩種調(diào)用格式,可以根據(jù)需要分別用來(lái)創(chuàng)建工作者線程和用戶界面線程。,一、AfxBeginThread函數(shù)用來(lái)創(chuàng)建工作者線程的調(diào)用格式:,16.3.1 線程的創(chuàng)建,CWinThread* AfxBeginThread( AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriori
7、ty = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );,pfnThreadProc:線程函數(shù)的地址,該參數(shù)不能設(shè)置為NULL,線程函數(shù)必須定義成全局函數(shù)或者類(lèi)的靜態(tài)成員函數(shù)。,例如:UINT myThreadFunc(LPVOID lparam)或者class Apublic:static UINT _stdcall myThreadFunc(LPVOID lparam);,1.參數(shù)說(shuō)明:,16.3.1 線
8、程的創(chuàng)建,pParam:要傳遞給線程函數(shù)的參數(shù);,nPriority:要啟動(dòng)的線程的優(yōu)先級(jí),默認(rèn)優(yōu)先級(jí)為T(mén)HREAD_PRIORITY_NORMAL(普通優(yōu)先級(jí)),關(guān)于線程優(yōu)先級(jí)的詳細(xì)說(shuō)明見(jiàn)16.4.2;,nStackSize:新線程的堆棧大小,如果設(shè)置為0,則使用默認(rèn)大小,在應(yīng)用程序中一般情況下線程的默認(rèn)堆棧大小為1M;,16.3.1 線程的創(chuàng)建,lpSecurityAttrs :指向SECURITY_ATTRIBUTES結(jié)構(gòu)的指針,結(jié)構(gòu)中指定了線程的安全屬性。如果為NULL,則與創(chuàng)建它的線程的安全屬性相同。,dwCreateFlags:線程創(chuàng)建標(biāo)志,該參數(shù)指定線程的初始狀態(tài),它可以被指定為
9、下列標(biāo)志: 0:線程在創(chuàng)建后立即執(zhí)行 CREATE_SUSPENDED:線程在創(chuàng)建后立即掛起,16.3.1 線程的創(chuàng)建,16.函數(shù)返回值的說(shuō)明:,函數(shù)AfxBeginThread返回指向CWinThread類(lèi)的指針。,16.3.1 線程的創(chuàng)建,3.創(chuàng)建工作者線程的過(guò)程:,利用函數(shù)AfxBeginThread創(chuàng)建工作者線程需要兩步:,1) 編寫(xiě)線程控制函數(shù);,2) 調(diào)用函數(shù)AfxBeginThread啟動(dòng)線程,將線程控制函數(shù)的地址作為第一個(gè)參數(shù),線程控制函數(shù)的參數(shù)作為第二個(gè)參數(shù)賦給AfxBeginThread函數(shù),,16.3.1 線程的創(chuàng)建,在應(yīng)用程序中,可以創(chuàng)建一個(gè)指向CWinThread類(lèi)的
10、指針,用來(lái)保存AfxBeginThread函數(shù)的返回值,即AfxBeginThread函數(shù)創(chuàng)建成功的線程類(lèi)CWinThread, 以便創(chuàng)建好的線程進(jìn)行控制,例如:,4.其它說(shuō)明:,16.3.1 線程的創(chuàng)建,CWinThread* pWinThread; pWinThread=AfxBeginThread( ControlFunction, pParam, THREAD_PRIORTY_NORMAL, 0, CREATE_SUSPENDED, NULL);,16.3.1 線程的創(chuàng)建,pWinThread-m_bAutoDelete=false; delete pWinThread;,這時(shí)應(yīng)注意:
11、,即要將CWinThread類(lèi)的數(shù)據(jù)成員m_bAutoDelete設(shè)為false,并且在退出進(jìn)程前,將指向線程類(lèi)CWinThread的指針pWinThread刪除。,16.3.1 線程的創(chuàng)建,二、AfxBeginThread函數(shù)用來(lái)創(chuàng)建用戶界面線程的調(diào)用格式:,CWinThread* AfxBeginThread( CRuntimeClass* pThreadClass, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSe
12、curityAttrs = NULL );,16.3.1 線程的創(chuàng)建,pfnThreadProc: 指向CRuntimeClass類(lèi)的指針。 其它參數(shù)的說(shuō)明與前面相同。,1.參數(shù)說(shuō)明:,16.創(chuàng)建用戶界面線程的過(guò)程:,1) 從CWinThread類(lèi)派生一個(gè)新類(lèi),派生類(lèi)必須用DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE宏來(lái)聲明和實(shí)現(xiàn);,16.3.1 線程的創(chuàng)建,2) 重載派生類(lèi)的InitInstance、ExitInstance等函數(shù),在InitInstance函數(shù)中添加代碼。,四、通過(guò)例題演示利用AfxBeginThread函數(shù)創(chuàng)建工作者線程和用戶界面線程的過(guò)程。
13、,16.3.1 線程的創(chuàng)建,三、關(guān)于CreateThread( )函數(shù)的一些說(shuō)明: 見(jiàn)附帶文件2。,16.3.2 線程的啟動(dòng),線程啟動(dòng)時(shí)的初始狀態(tài)可以通過(guò)AfxBeginThread( )函數(shù)的dwCreateFlags參數(shù)指定。如下:,0:線程在創(chuàng)建后立即執(zhí)行; CREATE_SUSPENDED:線程在創(chuàng)建后立即掛起;,所謂掛起就是暫停線程的執(zhí)行。,16.3.3 線程的終止,遇到以下情況時(shí),線程終止執(zhí)行:,1.線程控制函數(shù)返回(即執(zhí)行了return語(yǔ)句)。,16.線程自身調(diào)用函數(shù)ExitThread( )函數(shù)即終止自己。該函數(shù)的原型如下: VOID WINAPI ExitThread(DWO
14、RD dwExitCode ); 該函數(shù)通過(guò)參數(shù)dwExitCode給線程設(shè)置退出碼后,即終止線程的執(zhí)行。,16.3.3 線程的終止,3.同一進(jìn)程或其他進(jìn)程的線程調(diào)用TerminateThread函數(shù),其原型為: BOOL TerminateThread( HANDLE hThread, DWORD dwExitCode );,該函數(shù)用來(lái)結(jié)束由hThread參數(shù)指定的線程,并把dwExitCode設(shè)成該線程的退出碼。當(dāng)某個(gè)線程不再響應(yīng)時(shí),我們可以用其他線程調(diào)用該函數(shù)來(lái)終止這個(gè)不響應(yīng)的線程。,16.3.3 線程的終止,4.包含線程的進(jìn)程被終止,如其它進(jìn)程調(diào)用TerminateProcess函數(shù)終
15、止進(jìn)程的執(zhí)行,或進(jìn)程自身調(diào)用ExitProcess函數(shù)終止自身的執(zhí)行。,BOOL WINAPI TerminateProcess( HANDLE hProcess, UINT uExitCode );,TerminateProcess函數(shù)的原型為:,VOID WINAPI ExitProcess( UINT uExitCode );,ExitProcess函數(shù)的原型為:,16.3.3 線程的終止,5. 調(diào)用全局函數(shù)AfxEndThread終止進(jìn)程;,注意:最好使用第1種方式終止線程,第24種方式都不宜采用。,16.4.1 線程的運(yùn)行狀態(tài)的設(shè)置,16.4 線程的操作和管理,1.當(dāng)參數(shù)dwCrea
16、teFlags置為0時(shí),調(diào)用AfxBeginThread函數(shù)創(chuàng)建的線程一啟動(dòng)就立即執(zhí)行。這時(shí),如果想暫停該線程的執(zhí)行,可調(diào)用其成員函數(shù)SuspendedThread( )函數(shù)將自身掛起。,AfxEndThread函數(shù)的dwCreateFlags參數(shù)是決定線程在創(chuàng)建時(shí)的運(yùn)行狀態(tài)的。,16.4.1 線程的運(yùn)行狀態(tài)的設(shè)置,16.當(dāng)參數(shù)dwCreateFlags置為CREATE_SUSPENDED時(shí),調(diào)用AfxBeginThread函數(shù)創(chuàng)建的線程一啟動(dòng)就掛起,暫停執(zhí)行。這時(shí),如果想繼續(xù)執(zhí)行線程,可調(diào)用成員函數(shù)ResumeThread( )函數(shù)喚醒被掛起的線程。,被掛起的線程不能調(diào)用此函數(shù)喚醒自身,必須
17、由一個(gè)未被掛起的處于運(yùn)行狀態(tài)的線程調(diào)用此函數(shù)來(lái)取消掛起。,注意:,16.4.2 線程的優(yōu)先級(jí),一、 Windows操作系統(tǒng)是根據(jù)進(jìn)程和線程的優(yōu)先級(jí)來(lái)確定它們的排隊(duì)順序并分配CPU時(shí)間的,所以對(duì)于進(jìn)程和線程在其創(chuàng)建時(shí)要設(shè)置優(yōu)先級(jí)。,二、 線程的優(yōu)先級(jí)是根據(jù)其創(chuàng)建時(shí)設(shè)置的優(yōu)先級(jí)和擁有該線程的進(jìn)程的優(yōu)先級(jí)來(lái)確定的。其最終的優(yōu)先級(jí)是0到31之間的數(shù)值,數(shù)值越大,優(yōu)先級(jí)越高。其中,015級(jí)是普通優(yōu)先級(jí),16 30級(jí)是實(shí)時(shí)優(yōu)先級(jí)。,16.4.2 線程的優(yōu)先級(jí),Windows操作系統(tǒng)對(duì)具有普通優(yōu)先級(jí)的線程的調(diào)度特點(diǎn)是: 高優(yōu)先級(jí)線程先運(yùn)行,只有高優(yōu)先級(jí)線程不運(yùn)行時(shí),才調(diào)度低優(yōu)先級(jí)線程運(yùn)行。優(yōu)先級(jí)相同的線程按
18、照時(shí)間片輪流運(yùn)行。,三、Windows操作系統(tǒng)對(duì)線程的調(diào)度特點(diǎn),16.4.2 線程的優(yōu)先級(jí),四、Windows操作系統(tǒng)對(duì)具有實(shí)時(shí)優(yōu)先級(jí)的線程的調(diào)度特點(diǎn)是: 高優(yōu)先級(jí)線程先運(yùn)行,只有高優(yōu)先級(jí)線程不運(yùn)行時(shí),才調(diào)度低優(yōu)先級(jí)線程運(yùn)行。優(yōu)先級(jí)相同的線程不按照時(shí)間片輪轉(zhuǎn),而是先運(yùn)行的線程就先控制CPU,如果它不主動(dòng)放棄控制,同級(jí)或低優(yōu)先級(jí)的線程就無(wú)法運(yùn)行。,16.4.2 線程的優(yōu)先級(jí),五、 用函數(shù)AfxBeginThread創(chuàng)建線程時(shí),其參數(shù)nPriority指定新線程的優(yōu)先級(jí),該參數(shù)的取值為以下七個(gè)值之一:,THREAD_PRIORITY_TIME_CRITICAL THREAD_PRIORITY_HI
19、GHEST THREAD_PRIORITY_ABOVE_NORMAL THREAD_PRIORITY_NORMAL THREAD_PRIORITY_BELOW_NORMAL THREAD_PRIORITY_LOWEST THREAD_PRIORITY_IDLE,16.4.2 線程的優(yōu)先級(jí),對(duì)這七個(gè)值的說(shuō)明,及線程最終優(yōu)先級(jí)的確定: 見(jiàn)附帶文件3。,六、如何改變線程的優(yōu)先級(jí)?,在應(yīng)用程序中,如果需要改變線程的優(yōu)先級(jí),可以通過(guò)線程類(lèi)的成員函數(shù)SetThreadPriority( )對(duì)線程的優(yōu)先級(jí)重新設(shè)置。其原型如下: BOOL SetThreadPriority(int nPriority) 成功
20、執(zhí)行后返回非零值,不成功返回0。,16.4.2 線程的優(yōu)先級(jí),七、如何獲得線程的優(yōu)先級(jí)?,在應(yīng)用程序中,有時(shí)需要查詢線程的優(yōu)先級(jí),這時(shí)可以通過(guò)線程類(lèi)的成員函數(shù)GetThreadPriority( )獲得線程的優(yōu)先級(jí)。其原型如下: int GetThreadPriority( HANDLE hThread ) 返回THREAD_PRIORITY_ERROR_RETURN 表示失敗。成功時(shí)返回優(yōu)先級(jí)的七個(gè)值。,16.4.2 線程的優(yōu)先級(jí),八、Windows動(dòng)態(tài)調(diào)度線程的說(shuō)明,線程的優(yōu)先級(jí)不是一直不變的,Windows操作系統(tǒng)對(duì)線程從優(yōu)先級(jí)進(jìn)行動(dòng)態(tài)調(diào)整,以保證所有的線程都能較好的運(yùn)行。 當(dāng)線程長(zhǎng)時(shí)間
21、掛起以等待激活它再次運(yùn)行的信號(hào)時(shí),比它優(yōu)先級(jí)低的線程將難以得到所需的CPU時(shí)間。這種情況下,當(dāng)如果某線程在一段時(shí)間沒(méi)有運(yùn)行,Windows操作系統(tǒng)將提高它的優(yōu)先級(jí)以保證其獲得CPU時(shí)間。,16.4.3 線程間的通信,一、用簡(jiǎn)單的布爾型變量實(shí)現(xiàn)線程間的通信 見(jiàn)P40例題,二、通過(guò)消息的發(fā)送和處理來(lái)實(shí)現(xiàn)線程和主程序之間的通信,1.調(diào)用:PostMessage( ),其原型為:,16.4.3 線程間的通信,BOOLPostMessage( HWND hWnd, /要發(fā)送到的窗口的句柄 UINT Msg, /消息的ID值 WPARAM wParam, /消息的第一個(gè)參數(shù) LPARAM lParam /
22、消息的第二個(gè)參數(shù) );,如果執(zhí)行成功返回非零值,不成功返回0。,16.4.3 線程間的通信,實(shí)現(xiàn)方法:,1)在頭文件中定義一個(gè)消息,如線程終止的消息: const WM_THREADENDED WM_USER+10,2)加入相應(yīng)的消息處理函數(shù)的聲明: afx_msg LONG OnThreadended( WPARAM wParam, LPARAM lParam);,16.4.3 線程間的通信,3)在實(shí)現(xiàn)文件中,在消息映射部分,加入消息映射: ON_MESSGAE(WM_THREADENDED,OnThreadended),4)在線程中使用PostMessage( )函數(shù): PostMessa
23、ge(HWND)pParam,WM_THREADENDED,0,0),這個(gè)語(yǔ)句激活相應(yīng)的消息處理函數(shù),對(duì)WM_THREADENDED消息進(jìn)行處理,16.4.3 線程間的通信,16.調(diào)用CWinThread:PostThreadMessage( ), 其原型為:,BOOL PostThreadMessage( UINT message, /消息的ID值 WPARAM wParam, /消息的第一個(gè)參數(shù) LPARAM lParam /消息的第二個(gè)參數(shù) );,如果執(zhí)行成功返回非零值,不成功返回0。,三、使用同步類(lèi)來(lái)實(shí)現(xiàn)線程之間的通信和控制 在16.5小節(jié)中將詳細(xì)介紹,16.4.3 線程間的通信,16
24、.5 在VC+環(huán)境中使用同步對(duì)象,16.一個(gè)進(jìn)程的所有線程共享它的虛擬地址空間、全局變量和操作系統(tǒng)資源。,為什么要使用同步對(duì)象?,1.進(jìn)程由私有虛擬地址空間、代碼、數(shù)據(jù)和其它操作系統(tǒng)資源(如進(jìn)程創(chuàng)建的文件、同步對(duì)象等)組成。,3.如果對(duì)多個(gè)線程之間的資源訪問(wèn)不加以同步控制,這些線程在共享資源時(shí),容易產(chǎn)生訪問(wèn)沖突,產(chǎn)生不正確的結(jié)果。,16.5 在VC+環(huán)境中使用同步對(duì)象,例如在數(shù)據(jù)庫(kù)應(yīng)用程序中,需要同時(shí)存在兩個(gè)線程,一個(gè)負(fù)責(zé)讀數(shù)據(jù),一個(gè)負(fù)責(zé)寫(xiě)數(shù)據(jù)。這時(shí)就要謹(jǐn)防兩個(gè)線程同時(shí)對(duì)數(shù)據(jù)進(jìn)行操作。這時(shí)如果不進(jìn)行同步控制,讀線程所讀取的數(shù)據(jù),其狀態(tài)是不確定的。,所以當(dāng)有兩個(gè)或多個(gè)線程在共享數(shù)據(jù)時(shí),要使用同步
25、對(duì)象以確保這多個(gè)線程不會(huì)同時(shí)訪問(wèn)共享資源。,16.5 在VC+環(huán)境中使用同步對(duì)象,CSyncObject,CEvent,CObject,CCriticalSection,CMutex,CSemaphore,MFC中的同步類(lèi),16.5.1 事件對(duì)象,CEvent類(lèi)提供了對(duì)事件的支持。事件是一個(gè)允許一個(gè)線程在某種情況發(fā)生時(shí),喚醒另外一個(gè)線程的同步對(duì)象。事件告訴線程何時(shí)去執(zhí)行某一給定的任務(wù),從而使多個(gè)線程流平滑。,每一個(gè)CEvent對(duì)象可以有兩種狀態(tài):有信號(hào)狀態(tài)(signaled)和無(wú)信號(hào)狀態(tài)(nonsignaled)。線程監(jiān)視位于其中的CEvent類(lèi)對(duì)象的狀態(tài),并在相應(yīng)的時(shí)候采取相應(yīng)的操作。,16
26、.5.1 事件對(duì)象,CEvent類(lèi)的成員:,構(gòu)造函數(shù)CEvent,PulseEvent函數(shù),Unlock函數(shù),ResetEvent函數(shù),SetEvent函數(shù),下面分別介紹CEvent類(lèi)的這些成員函數(shù)。,16.5.1 事件對(duì)象,1.構(gòu)造函數(shù)CEvent的原型:,CEvent( BOOL bInitiallyOwn , BOOL bManualReset , LPCTSTR lpszName , LPSECURITY_ATTRIBUTES lpsaAttribute ),其參數(shù)說(shuō)明如下:,16.5.1 事件對(duì)象,bInitiallyOwn: 若bInitiallyOwn為T(mén)RUE,則使CMulti
27、lock類(lèi)對(duì)象和CSingleLock類(lèi)對(duì)象的線程可用;否則,要訪問(wèn)資源的線程必須等待。該參數(shù)的默認(rèn)值為FALSE。,bManualReset: 指定要?jiǎng)?chuàng)建的CEvent對(duì)象是屬于手工事件對(duì)象還是自動(dòng)事件對(duì)象。若為T(mén)RUE,則為手工事件對(duì)象,否則為自動(dòng)事件對(duì)象。該參數(shù)默認(rèn)值為FALSE。,補(bǔ)充說(shuō)明:在MFC中,CEvent類(lèi)對(duì)象有兩種類(lèi)型,分別是所謂的手工事件和自動(dòng)事件。對(duì)于自動(dòng)事件,當(dāng)其獲得信號(hào)后,就會(huì)釋放下一個(gè)可用的線程。一個(gè)自動(dòng) CEvent對(duì)象在被至少一個(gè)線程釋放后會(huì)自動(dòng)返回到無(wú)信號(hào)狀態(tài);而人工事件對(duì)象獲得信號(hào)后,釋放所有可利用線程,直到調(diào)用成員函數(shù)ReSetEvent()將其設(shè)置為無(wú)
28、信號(hào)狀態(tài)時(shí)為止。 注意:在創(chuàng)建CEvent類(lèi)的對(duì)象時(shí),默認(rèn)創(chuàng)建的是自動(dòng)事件。,16.5.1 事件對(duì)象,16.5.1 事件對(duì)象,lpszName: 指定要?jiǎng)?chuàng)建的事件對(duì)象的名字,如果該事件對(duì)象將跨進(jìn)程使用,則此參數(shù)不能為NULL。如果該參數(shù)和一個(gè)已經(jīng)存在的CEvent對(duì)象相同,則該構(gòu)造函數(shù)返回一個(gè)對(duì)這個(gè)已存在對(duì)象的引用;如果參數(shù)和一個(gè)已存在的非CEvent類(lèi)的同步對(duì)象(如CMutex)相同,則對(duì)象創(chuàng)建失敗;,16.5.1 事件對(duì)象,lpsaAttribute: 指向SECURITY_ATTRIBUTES結(jié)構(gòu)的指針,該參數(shù)決定要?jiǎng)?chuàng)建的事件對(duì)象的安全屬性,一般置為NULL。,16.5.1 事件對(duì)象,將
29、CEvent類(lèi)對(duì)象的狀態(tài)設(shè)置為有信號(hào)狀態(tài),并且釋放所有等待的線程;如果該事件是人工事件,則CEvent類(lèi)對(duì)象保持為有信號(hào)狀態(tài),直到調(diào)用成員函數(shù)ResetEvent()將其重新設(shè)為無(wú)信號(hào)狀態(tài)時(shí)為止,這樣該事件就可以釋放多個(gè)線程;如果CEvent類(lèi)對(duì)象為自動(dòng)事件,則在SetEvent()將事件設(shè)置為有信號(hào)狀態(tài)后,CEvent類(lèi)對(duì)象由系統(tǒng)自動(dòng)重置為無(wú)信號(hào)狀態(tài),除非一個(gè)線程被釋放。 如果該函數(shù)執(zhí)行成功,則返回非零值,否則返回零。,16.5.1 事件對(duì)象,3. BOOL ResetEvent( ),該函數(shù)將事件的狀態(tài)設(shè)置為無(wú)信號(hào)狀態(tài),并保持該狀態(tài)直至SetEvent()被調(diào)用時(shí)為止。由于自動(dòng)事件是由系統(tǒng)
30、自動(dòng)重置,故自動(dòng)事件不需要調(diào)用該函數(shù)。 如果該函數(shù)執(zhí)行成功,返回非零值,否則返回非零。,16.5.1 事件對(duì)象,4. BOOL PulseEvent( ),發(fā)送一個(gè)事件脈沖,該函數(shù)完成一系列操作后才返回。對(duì)于自動(dòng)事件,PulseEvent()將事件設(shè)置為有信號(hào)狀態(tài),等待一個(gè)線程被釋放,將事件重置為無(wú)信號(hào)狀態(tài),然后PulseEvent()返回;對(duì)于人工事件,則將等待該事件的所有線程被釋放,事件被自動(dòng)重置為無(wú)信號(hào)狀態(tài),然后PulseEvent()返回。 一個(gè)CEvent對(duì)象在線程中被創(chuàng)建后,自動(dòng)處于無(wú)信號(hào)狀態(tài),但在另一個(gè)線程中可以調(diào)用Win32 API WaitForSingleObject()函
31、數(shù)來(lái)監(jiān)視其狀態(tài)。,16.5.1 事件對(duì)象,5. BOOL Unlock( ),如果線程擁有事件對(duì)象,并且事件對(duì)象是一個(gè)自動(dòng)事件對(duì)象,則返回非零值,否則返回0。,該函數(shù)用來(lái)釋放事件對(duì)象,即把Lock鎖定的線程解鎖。,16.5.1 事件對(duì)象,另外補(bǔ)充一個(gè)函數(shù) BOOL Lock( ),該函數(shù)不是CEvent類(lèi)的成員函數(shù),是CEvent的父類(lèi)CSyncObject類(lèi)的成員函數(shù),CEvent通過(guò)繼承可以使用該函數(shù)。,該函數(shù)用來(lái)鎖定事件對(duì)象,阻止線程的繼續(xù)執(zhí)行,直到事件對(duì)象處于活動(dòng)狀態(tài)為止。,6. WaitForSingleObject( ): 其原型聲明如下: DWORD WaitForSingleO
32、bject( HANDLE hHandle, DWORD dwMilliseconds ),hHandle為指向要監(jiān)視的同步對(duì)象的句柄; dwMilliseconds為監(jiān)視hHandle所指向的對(duì)象所設(shè)置的超時(shí)值,單位為毫秒。,16.5.1 事件對(duì)象,當(dāng)在線程的執(zhí)行函數(shù)中調(diào)用該函數(shù)時(shí),線程暫時(shí)掛起,系統(tǒng)監(jiān)視hHandle所指向的對(duì)象的狀態(tài)。如果經(jīng)過(guò)dwMilliseconds毫秒后,hHandle指向的對(duì)象變?yōu)橛行盘?hào)狀態(tài),則WaitForSingleObject()返回,線程被釋放,且返回值為WAIT_TIMEOUT;如果在掛起的dwMilliseconds毫秒內(nèi),線程所等待的對(duì)象在某一時(shí)刻變
33、為有信號(hào),則該函數(shù)立即返回,返回值為WAIT_OBJECT_0。,16.5.1 事件對(duì)象,參數(shù)dwMilliseconds有兩個(gè)具有特殊意義的值:0和INFINITE。若為0,則該函數(shù)立即返回;若為INFINITE,則線程一直被掛起,直到hHandle所指向的對(duì)象變?yōu)橛行盘?hào)狀態(tài)時(shí)為止。,16.5.1 事件對(duì)象,CEvent:ResetEvent( )把對(duì)象設(shè)置為無(wú)信號(hào)狀態(tài),程序在WaitForSingleObject(hHandle,INFINITE)處等待。 CEvent:SetEvent( )把對(duì)象設(shè)置為有信號(hào)狀態(tài),釋放等待的線程。 如果CEvent對(duì)象為自動(dòng)事件,則當(dāng)WaitForSin
34、gleObject(hHandle,INFINITE)返回時(shí),自動(dòng)把CEvent對(duì)象重置為無(wú)信號(hào)狀態(tài)。,16.5.1 事件對(duì)象,總結(jié)以上,幾個(gè)函數(shù)的使用順序?yàn)椋?B線程在執(zhí)行到CEvent類(lèi)成員函數(shù)Lock( )時(shí)將會(huì)發(fā)生阻塞,而A線程此時(shí)則可以在沒(méi)有B線程干擾的情況下對(duì)共享資源進(jìn)行處理,并在處理完成后通過(guò)成員函數(shù)SetEvent( )向B發(fā)出事件,使其被釋放,得以對(duì)A先前已處理完畢的共享資源進(jìn)行操作。,16.5.1 事件對(duì)象,另外通過(guò)一個(gè)例題來(lái)演示事件的工作原理:,16.5.2 臨界區(qū),臨界區(qū)(Critical Section)是一段代碼,該代碼獨(dú)占對(duì)某些共享資源的訪問(wèn),在任意時(shí)刻只允許一個(gè)
35、線程對(duì)共享資源進(jìn)行訪問(wèn)。如果有多個(gè)線程試圖同時(shí)訪問(wèn)臨界區(qū),那么在有一個(gè)線程進(jìn)入后其他所有試圖訪問(wèn)此臨界區(qū)的線程將被掛起,并一直持續(xù)到進(jìn)入臨界區(qū)的線程離開(kāi)。 臨界區(qū)在被釋放后,其他線程可以繼續(xù)搶占,并以此達(dá)到用原子方式操作共享資源的目的。,16.5.2 臨界區(qū),在使用臨界區(qū)時(shí),一般不允許其運(yùn)行時(shí)間過(guò)長(zhǎng),只要進(jìn)入臨界區(qū)的線程還沒(méi)有離開(kāi),其他所有試圖進(jìn)入此臨界區(qū)的線程都會(huì)被掛起而進(jìn)入到等待狀態(tài),并會(huì)在一定程度上影響。程序的運(yùn)行性能。尤其需要注意的是不要將等待用戶輸入或是其他一些外界干預(yù)的操作包含到臨界區(qū)。如果進(jìn)入了臨界區(qū)卻一直沒(méi)有釋放,同樣也會(huì)引起其他線程的長(zhǎng)時(shí)間等待。,16.5.2 臨界區(qū),雖然臨
36、界區(qū)同步速度很快,但卻只能用來(lái)同步本進(jìn)程內(nèi)的線程,而不可用來(lái)同步多個(gè)進(jìn)程中的線程。,MFC為臨界區(qū)提供有一個(gè)CCriticalSection類(lèi),使用該類(lèi)進(jìn)行線程同步處理是非常簡(jiǎn)單的,只需在線程函數(shù)中用CCriticalSection類(lèi)成員函數(shù)Lock()和UnLock()標(biāo)定出被保護(hù)的代碼片段即可。,16.5.2 臨界區(qū),下面通過(guò)一段代碼展示了臨界區(qū)在保護(hù)多線程訪問(wèn)的共享資源中的作用。通過(guò)兩個(gè)線程來(lái)分別對(duì)全局變量g_cArray10進(jìn)行寫(xiě)入操作,用臨界區(qū)對(duì)象g_clsCriticalSection來(lái)保持線程的同步,并在開(kāi)啟線程前對(duì)其進(jìn)行初始化。為了使實(shí)驗(yàn)效果更加明顯,體現(xiàn)出臨界區(qū)的作用,在線程
37、函數(shù)對(duì)共享資源g_cArray10的寫(xiě)入時(shí),以Sleep( )函數(shù)延遲1毫秒,使其他線程同其搶占CPU的可能性增大。如果不使用臨界區(qū)對(duì)其進(jìn)行保護(hù),則共享資源數(shù)據(jù)將被破壞。而使用臨界區(qū)對(duì)線程保持同步后則可以得到正確的結(jié)果。,16.5.3 互斥量,互斥量(Mutex)是一種用途非常廣泛的內(nèi)核對(duì)象。能夠保證多個(gè)線程對(duì)同一共享資源的互斥訪問(wèn)。同臨界區(qū)有些類(lèi)似,只有擁有互斥對(duì)象的線程才具有訪問(wèn)資源的權(quán)限,由于互斥對(duì)象只有一個(gè),因此就決定了任何情況下此共享資源都不會(huì)同時(shí)被多個(gè)線程所訪問(wèn)。當(dāng)前占有資源的線程在任務(wù)處理完后應(yīng)將擁有的互斥對(duì)象交出,以便其他線程在獲得后得以訪問(wèn)共享資源。,圖:互斥內(nèi)核對(duì)象的工作模
38、型,16.5.3 互斥量,與其他幾種內(nèi)核對(duì)象不同,互斥對(duì)象在操作系統(tǒng)中擁有特殊代碼,并由操作系統(tǒng)來(lái)管理,操作系統(tǒng)甚至還允許其進(jìn)行一些其他內(nèi)核對(duì)象所不能進(jìn)行的非常規(guī)操作。為便于理解,可參照下圖。,共享資源,擁有互斥量的線程,16.5.3 互斥量,互斥對(duì)象在MFC中通過(guò)CMutex類(lèi)進(jìn)行表述。使用CMutex類(lèi)的方法非常簡(jiǎn)單,在構(gòu)造CMutex類(lèi)對(duì)象的同時(shí)可以指明待查詢的互斥對(duì)象的名字,在構(gòu)造函數(shù)返回后即可訪問(wèn)此互斥變量。CMutex類(lèi)也是只含有構(gòu)造函數(shù)這唯一的成員函數(shù),當(dāng)完成對(duì)互斥對(duì)象保護(hù)資源的訪問(wèn)后,可通過(guò)調(diào)用從父類(lèi)CSyncObject繼承的UnLock()函數(shù)完成對(duì)互斥對(duì)象的釋放。,16.5.3 互斥量,CMutex類(lèi)構(gòu)造函數(shù)原型為:,其參數(shù)說(shuō)明如下:,CMutex( BOOL bInitiallyOwn = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTE SlpsaAttribute = NULL ),16.5.3 互斥量,bInitiallyOwn: 該參數(shù)指定是否創(chuàng)建了CMutex對(duì)象的線程最初擁有由互斥量CMutex控制的共享資源的控制權(quán)。,16.5.3 互斥量,lpszName: 指定要?jiǎng)?chuàng)建的CMute
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 電影放映設(shè)備裝配調(diào)試工班組管理水平考核試卷含答案
- 工業(yè)氣體液化工崗前核心能力考核試卷含答案
- 因孩子拉肚子請(qǐng)假條
- 2025年節(jié)能技術(shù)服務(wù)項(xiàng)目發(fā)展計(jì)劃
- 2025年潛水及水下救撈裝備合作協(xié)議書(shū)
- 信息安全培訓(xùn)課件博客
- 2025 小學(xué)一年級(jí)科學(xué)下冊(cè)莖干的繁殖方法課件
- 2026年1月20日內(nèi)蒙古國(guó)際蒙醫(yī)醫(yī)院面試真題及答案解析(下午卷)
- 2026年智能腕力球項(xiàng)目公司成立分析報(bào)告
- 建筑工程公司施工員崗位工作總結(jié)
- 【麗江玉龍旅游薪酬制度的創(chuàng)新研究6100字】
- 公司兩權(quán)分離管理制度
- 車(chē)輛叉車(chē)日常檢查記錄表
- 廣東高校畢業(yè)生“三支一扶”計(jì)劃招募考試真題2024
- 膠帶機(jī)硫化工藝.課件
- 種雞免疫工作總結(jié)
- 河南省商丘市柘城縣2024-2025學(xué)年八年級(jí)上學(xué)期期末數(shù)學(xué)試題(含答案)
- 河南省信陽(yáng)市2024-2025學(xué)年高二上學(xué)期1月期末英語(yǔ)試題(含答案無(wú)聽(tīng)力原文及音頻)
- 給女朋友申請(qǐng)書(shū)
- 八下《桃花源記》《小石潭記》全文背誦(原文+譯文)
- 【8地RJ期末】安徽省蕪湖市2024-2025學(xué)年八年級(jí)上學(xué)期期末考試地理試卷+
評(píng)論
0/150
提交評(píng)論