版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第11章MFC的進(jìn)程和線程本章講述多線程編程技術(shù)。11.1Win32的進(jìn)程和線程概念首先有必要了解一下進(jìn)程和線程的概念。11.1.1進(jìn)程的概念進(jìn)程的定義是為執(zhí)行程序指令的線程而保留的一系列資源的集合。進(jìn)程是一個(gè)可執(zhí)行的程序,由私有虛擬地址空間、代碼、數(shù)據(jù)和其他操作系統(tǒng)資源(如進(jìn)程創(chuàng)建的文件、管道、同步對(duì)象等)組成。進(jìn)程是一些所有權(quán)的集合,一個(gè)進(jìn)程擁有內(nèi)存,CPU運(yùn)行時(shí)間等一系列資源,為線程的運(yùn)行提供一個(gè)環(huán)境,每個(gè)進(jìn)程都有它自己的地址空間和動(dòng)態(tài)分配的內(nèi)存,以及線程,文件和其他一些模塊。11.1.2線程的概念一個(gè)應(yīng)用程序可以有一個(gè)或多個(gè)進(jìn)程,一個(gè)進(jìn)程可以有一個(gè)或多個(gè)線程,其中一個(gè)是主線程。線程是操作系統(tǒng)分時(shí)調(diào)度分配CPU時(shí)間的基本實(shí)體。一個(gè)線程可以執(zhí)行程序的任意部分的代碼,即使這部分代碼被另一個(gè)線程并發(fā)地執(zhí)行;一個(gè)進(jìn)程的所有線程共享它的虛擬地址空間、全局變量和操作系統(tǒng)資源。11.2進(jìn)程編程因?yàn)镸FC沒(méi)有提供類處理進(jìn)程,所以直接使用了Win32API函數(shù)。11.2.1進(jìn)程的創(chuàng)建調(diào)用CreateProcess函數(shù)創(chuàng)建新的進(jìn)程,運(yùn)行指定的程序。CreateProcess的原型如下:BOOLCreateProcess(LPCTSTRlpApplicationName,LPTSTRlpCommandLine,LPSECURITY_ATTRIBUTESlpProcessAttributes,LPSECURITY_ATTRIBUTESlpThreadAttributes,BOOLbInheritHandles,DWORDdwCreationFlags,LPVOIDlpEnvironment,LPCTSTRlpCurrentDirectory,LPSTARTUPINFOlpStartupInfo,LPPROCESS_INFORMATIONlpProcessInformation);11.2.2進(jìn)程的管理和終止取得當(dāng)前進(jìn)程的句柄和ID需要以下兩個(gè)函數(shù):HANDLEGetCurrentProcess(void)DWORDGetCurrentProcessId(void)11.2.3取得和設(shè)置進(jìn)程的優(yōu)先級(jí)取得一個(gè)進(jìn)程的優(yōu)先級(jí)的函數(shù)如下:DWORDGetPriorityClass(HANDLEhProcess);其中,參數(shù)hProcess是要取得優(yōu)先級(jí)的進(jìn)程的句柄。設(shè)置一個(gè)進(jìn)程的優(yōu)先級(jí)的函數(shù)如下: BOOLSetPriorityClass(HANDLEhProcess,DWORDdwPriorityClass);11.2.4進(jìn)程的終止終止一個(gè)進(jìn)程有兩種方法:最常用的方法是調(diào)用函數(shù)ExitProcess()結(jié)束進(jìn)程。另一種方法是調(diào)用函數(shù)TerminateProcess終止進(jìn)程。在當(dāng)前進(jìn)程中的一個(gè)線程調(diào)用函數(shù)ExitProcess就會(huì)結(jié)束當(dāng)前進(jìn)程。VOIDExitProcess(UNITuExitCode);當(dāng)需要在當(dāng)前進(jìn)程中結(jié)束其他進(jìn)程時(shí),就需要用到另一種方法即調(diào)用函數(shù)TerminateProcess,其函數(shù)原形為:VOIDTerminateProcess(UNITuExitCode);11.2.5判斷一個(gè)進(jìn)程是否終止當(dāng)一個(gè)進(jìn)程終止或結(jié)束時(shí)就不能利用這個(gè)進(jìn)程的句柄再對(duì)該進(jìn)程進(jìn)行操作,這就需要判斷一個(gè)進(jìn)程是否終止,或者要看一個(gè)進(jìn)程是否正常的退出,也需要查看這個(gè)進(jìn)程的返回碼??梢岳煤瘮?shù)GetExitCodeProcess來(lái)判斷一個(gè)進(jìn)程是否終止,如果終止,則取得這個(gè)進(jìn)程的返回碼,否則返回標(biāo)志STILL_ACTIVE。BOOLGetExitCodeProcess(HANDLEhProcess,LPDWORDlpExitCode);11.3Win32中關(guān)于多線程的幾個(gè)函數(shù)下表11.1列出了Win32中關(guān)于多線程的幾個(gè)函數(shù)CreateThread創(chuàng)建一個(gè)新線程CreatRemoteThread在另一個(gè)進(jìn)程中創(chuàng)建一個(gè)新線程ExitThread正常的結(jié)束一個(gè)線程的執(zhí)行TerminateThread終止一個(gè)線程的執(zhí)行GetExitCodeThread得到另一個(gè)線程的退出碼GetThreadPriority得到線程的優(yōu)先級(jí)SetThreadPriority設(shè)置一個(gè)線程的優(yōu)先級(jí)SuspendThread掛起一個(gè)線程ResumeThread重啟一個(gè)線程CloseHand關(guān)閉一個(gè)線程的句柄11.3.1線程的創(chuàng)建使用CreateThread函數(shù)創(chuàng)建線程,CreateThread的原型如下:HANDLECreateThread(LPSECURITY_ATTRIBUTESlpThreadAttributes,DWORDdwStackSize,LPTHREAD_START_ROUTINElpStartAddress,LPVOIDlpParameter,DWORDdwCreationFlags,//creationflagsLPDWORDlpThreadId);11.3.2CreatRemoteThread函數(shù)該函數(shù)在其他進(jìn)程的虛擬地址空間創(chuàng)建線程。其聲明如下:HANDLECreatRemoteThread(HANDLEhProcess;LPSECURITY_ATTRIBUTESlpThreadAttributes,DWORDdwStackSize,LPTHREAD_START_ROUTINElpStartAddress,LPVOIDlpParameter,DWORDdwCreationFlags,//creationflagsLPDWORDlpThreadId);11.3.3SuspendThread和
ResumeThread函數(shù)SuspendThread()的作用為暫停一個(gè)線程,ResumeThread()的作用為重啟一個(gè)線程。它們都帶有一個(gè)HANDLE型的參數(shù),參數(shù)值為要暫?;蛑貑⒕€程的句柄。SuspendThread(HANDLEhThread);ResumeThread(HANDLEhThread);11.3.4ExitThread和TerminateThread函數(shù)終止一個(gè)線程有兩種方法:最常用的方法是調(diào)用函數(shù)ExitThread()結(jié)束線程。另一種方法是調(diào)用函數(shù)TerminateThread終止線程。在當(dāng)前線程中的一個(gè)線程調(diào)用函數(shù)ExitProcess就會(huì)結(jié)束當(dāng)前線程:VOIDExitThread(DWORDdwExitCode);這個(gè)函數(shù)用來(lái)結(jié)束當(dāng)前線程,其中參數(shù)用來(lái)存放此線程的退出碼。這是最正常的結(jié)束線程的方法。BOOLTerminateThread(HANDLEhThread.//線程句柄DWORDdwExitCode//線程退出碼);11.3.5取得一個(gè)線程的優(yōu)先級(jí)的函數(shù)獲得一個(gè)線程的優(yōu)先級(jí)的函數(shù):intGetThreadPriority(HANDLEhThread);參數(shù)hThread是要取得優(yōu)先級(jí)的線程的句柄。設(shè)置一個(gè)線程的優(yōu)先級(jí)的函數(shù):BOOLSetThreadPriority(HANDLEhThread,intnPriority);參數(shù)hThread是要取得優(yōu)先級(jí)線程的句柄,參數(shù)nPriority就是要設(shè)置的優(yōu)先級(jí)。11.4MFC中多線程的實(shí)現(xiàn)在Win32API的基礎(chǔ)之上,MFC提供了處理線程的類和函數(shù)。MFC對(duì)多線程進(jìn)行一種簡(jiǎn)單的封裝,其中每個(gè)線程都是從CWinThread類繼承而來(lái)的。每一個(gè)應(yīng)用程序的執(zhí)行都有一個(gè)主線程,主線程也是從CWinThread類繼承而來(lái)的??梢岳肅WinThread對(duì)象創(chuàng)建應(yīng)用程序執(zhí)行的其他線程。處理線程的類是CWinThread,它的成員變量m_hThread和m_hThreadID是對(duì)應(yīng)的Win32線程句柄和線程ID。MFC多線程編程中經(jīng)常用到的幾個(gè)全局函數(shù)是AfxBeginThread、AfxEndThread等。MFC明確區(qū)分兩種線程:用戶界面線程(Userinterfacethread)和工作者線程(Workerthread)。用戶界面線程一般用于處理用戶輸入并對(duì)用戶產(chǎn)生的事件和消息作出應(yīng)答。工作者線程用于完成不要求用戶輸入的任務(wù),如實(shí)時(shí)數(shù)據(jù)采集、計(jì)算等。11.4.1與多線程編程相關(guān)的全局函數(shù)AfxBeginThread用戶界面線程和工作者線程都是由AfxBeginThread創(chuàng)建的。:用戶界面線程的AfxBeginThread的原型如下:CWinThread*AFXAPIAfxBeginThread(CRuntimeClass*pThreadClass,intnPriority,UINTnStackSize,DWORDdwCreateFlags,LPSECURITY_ATTRIBUTESlpSecurityAttrs)11.4.1與多線程編程相關(guān)的全局函數(shù)(續(xù))工作者線程的AfxBeginThread的原型如下:CWinThread*AFXAPIAfxBeginThread(AFX_THREADPROCpfnThreadProc,LPVOIDpParam,intnPriority,UINTnStackSize,DWORDdwCreateFlags,LPSECURITY_ATTRIBUTESlpSecurityAttrs)11.4.1與多線程編程相關(guān)的全局函數(shù)(續(xù))CWinThread*AFXAPIAfxGetThread();該全局函數(shù)用來(lái)獲取線程對(duì)象。VOIDAFXAPIAfxEndThread(UNITnExitCode,BOOLbDelete=TRUE);該函數(shù)用來(lái)結(jié)束線程的執(zhí)行。VOIDAFXAPIAfxInitThread();初始化進(jìn)程函數(shù)。VOIDAFXAPIAfxTermThread(HINSTANCEhInstTerm=NULL);終止線程執(zhí)行函數(shù)。11.4.2CWinThread類CWinThread類封裝了上節(jié)講的API函數(shù),并且增加了新的函數(shù)和屬性。至于其類的具體聲明在afxwin.h中。11.4.3工作者線程的創(chuàng)建工作線程經(jīng)常來(lái)完成一些后臺(tái)工作,如計(jì)算,打印等,這樣用戶就不必因?yàn)橛?jì)算機(jī)在從事繁雜而耗時(shí)的工作而等待。需要向AfxBeginThread()函數(shù)提供線程函數(shù)的起始地址和傳給線程函數(shù)的參數(shù)。線程函數(shù)的格式如下:UNIT函數(shù)名(LPVOIDpParam)11.4.4創(chuàng)建用戶界面線程用戶界面線程的創(chuàng)建有兩種方法。方法一是首先從CWinThread類派生一個(gè)類(需要用宏DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE對(duì)該類進(jìn)行聲明和實(shí)現(xiàn)),然后調(diào)用函數(shù)AfxBeginThread()創(chuàng)建CWinThread派生類的對(duì)象進(jìn)行初始化,啟動(dòng)線程執(zhí)行。方法二先通過(guò)構(gòu)造函數(shù)創(chuàng)建類的一個(gè)對(duì)象,然后由程序員調(diào)用函數(shù)CWinThread::CreateThread來(lái)啟動(dòng)線程。通常CWinThread類的對(duì)象在該線程的生存期結(jié)束時(shí)將自動(dòng)終止,如果程序員希望自己來(lái)控制,則需要將m_AutoDelete設(shè)為FALSE。這樣在線程終止之后,CWinThread類對(duì)象仍然存在,此時(shí)需要手動(dòng)刪除CWinThread對(duì)象。11.5線程之間的通信線程通信一般有四種方式:全局變量方式,消息傳遞方式,參數(shù)傳遞方式和線程同步方式。全局變量方式:在一個(gè)進(jìn)程中共享全局變量就可以通過(guò)全局變量來(lái)進(jìn)行線程間的通信參數(shù)傳遞方式:主線程在創(chuàng)建子進(jìn)程的時(shí)候,可以通過(guò)傳給線程函數(shù)的參數(shù)和其通信。所傳遞的參數(shù)是一個(gè)32位的指針,該指針可以指向簡(jiǎn)單的數(shù)據(jù),也可以指向結(jié)構(gòu)甚至更復(fù)雜的數(shù)據(jù)類型。通過(guò)參數(shù)的傳遞能在兩個(gè)線程函數(shù)之間傳遞很復(fù)雜的數(shù)據(jù)。消息傳遞法:通過(guò)函數(shù)在主線程和工作線程之間傳遞消息,通過(guò)函數(shù)在用戶界面線程和其他線程之間傳遞消息,消息傳遞是一種很重要的線程之間的通信方式。線程之間通信的一種重要的方法就是線程同步,將在下一節(jié)給予介紹。11.6線程的調(diào)度和同步Win32提供了一組對(duì)象用來(lái)實(shí)現(xiàn)多線程的同步。它們是Critical_section(關(guān)鍵段),Event(事件),Mutex(互斥對(duì)象),Semaphores(信號(hào)量)。MFC封裝了這幾個(gè)同步對(duì)象,它們分別是:CCritical_section、Cevent、Cmutex、Csemaphores。這四個(gè)同步類都以CsyncObject為它們的父類。11.6.1臨界段對(duì)象臨界段對(duì)象一次只允許一個(gè)線程取得一個(gè)數(shù)據(jù)區(qū)進(jìn)行操作。這時(shí)候可以創(chuàng)建臨界段對(duì)象,并且使用這個(gè)臨界段對(duì)象進(jìn)行相應(yīng)的操作以實(shí)現(xiàn)線程的同步。定義一個(gè)臨界段對(duì)象。臨界段對(duì)象的變量類型是CRITICAL_SECTION:CRITICAL_SECTION對(duì)象名;然后調(diào)用函數(shù)InitializeCriticalSection初始化該對(duì)象。初始化時(shí)把對(duì)象設(shè)置為NOT_SINGALED,表示允許線程使用資源:函數(shù)說(shuō)明如下:InitializeCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);11.6.1臨界段對(duì)象(續(xù))進(jìn)入和離開(kāi)臨界區(qū)。如果一段程序代碼需要對(duì)某個(gè)資源進(jìn)行同步保護(hù),則這是一段臨界段代碼。在進(jìn)入該關(guān)鍵段代碼前調(diào)用EnterCriticalSection函數(shù),這樣,其他線程都不能執(zhí)行該段代碼,若它們?cè)噲D執(zhí)行就會(huì)被阻塞。完成關(guān)鍵段的執(zhí)行之后,調(diào)用LeaveCriticalSection函數(shù),其他的線程就可以繼續(xù)執(zhí)行該段代碼。如果該函數(shù)不被調(diào)用,則其他線程將無(wú)限期的等待。VOIDEnterCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);VOIDLeaveCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);兩個(gè)函數(shù)的參數(shù)lpCriticalSection是指向CRITICAL_SECTION結(jié)構(gòu)的指針。11.6.2互斥對(duì)象互斥對(duì)象的工作方式和臨界段對(duì)象非常相似,其區(qū)別在于互斥量不僅保護(hù)一個(gè)進(jìn)程內(nèi)的共享資源,而且保護(hù)系統(tǒng)中進(jìn)程之間的資源,它是通過(guò)互斥量提供一個(gè)互斥量名來(lái)實(shí)現(xiàn)進(jìn)程和線程之間共享協(xié)調(diào)的。在使用互斥量進(jìn)行同步線程前,必須首先創(chuàng)建互斥量可以調(diào)用CreateMutex函數(shù)創(chuàng)建互斥量,其函數(shù)說(shuō)明如下:HANDLECreateMutex(LPSECURITY_ATTRIBUTESlpMutexAttributes,BOOLbInitialOwner;LPCSTRlpName);11.6.2互斥對(duì)象(續(xù))打開(kāi)互斥量的函數(shù) OpenMutex( DWORDdwDesiredAccess,BOOLbInitialOwner;LPCSTRlpName );獲得互斥量: 獲得互斥量的函數(shù)如下: DWORDSignalObjectAndWait( HANDLEhObjectToSignal,HANDLEhObjectToWaitOn, DWORDdwMilliseconds,BOOLbAlertable );釋放互斥量:調(diào)用函數(shù)RealseMutex可以釋放互斥量:BOOLRealseMutex(HANDLEhMutex);11.6.3事件對(duì)象事件和互斥量的區(qū)別如下:事件主要用于協(xié)調(diào)兩個(gè)和多個(gè)線程之間的動(dòng)作,使其協(xié)調(diào)一致,符合邏輯。一個(gè)線程等待某個(gè)事件的發(fā)生,另一個(gè)線程則在某個(gè)事件發(fā)生后產(chǎn)生一個(gè)信號(hào),通知正在等待的線程,而互斥量主要是保證任一時(shí)刻只有一個(gè)線程在使用共享的資源,什么時(shí)刻運(yùn)行哪個(gè)線程是隨機(jī)的,是由操作系統(tǒng)決定的,用戶沒(méi)有任何決定權(quán),所以互斥量不能使兩個(gè)線程按一定順序執(zhí)行。有信號(hào)和無(wú)信號(hào)的含義不同:對(duì)于互斥量來(lái)講,有信號(hào)狀態(tài)就是指線程正在擁有互斥量,其他線程不能獲得互斥量,無(wú)信號(hào)是指沒(méi)有線程擁有互斥量,其他線程可以獲得互斥量,訪問(wèn)被互斥量保護(hù)的資源。對(duì)于事件而講,當(dāng)?shù)却氖录l(fā)生時(shí),事件對(duì)象處于有信號(hào)狀態(tài);相反當(dāng)?shù)却氖录](méi)有發(fā)生時(shí),稱事件處于無(wú)信號(hào)狀態(tài)。11.6.3事件對(duì)象(續(xù))創(chuàng)建和打開(kāi)事件對(duì)象: 在利用事件之前,必須先調(diào)用CreateEvent函數(shù)創(chuàng)建一個(gè)事件對(duì)象 HANDLECreateEvent( LPSECURITY_ATTRIBUTESlpEventAttributes,BOOLbInitialState;BOOLbManulReset;LPCSTRlpName ); HANDLEOpenEvent( DWORDdwDesiredAccess,BOOLbInitialHandle;LPCSTRlpName );設(shè)置和重置事件對(duì)象: BOOLSetEvent(HANDLEhEvent); 該函數(shù)觸發(fā)一個(gè)事件,即將事件置為有信號(hào)狀態(tài)。 BOOLResetEvent(HANDLEhEvent); 該函數(shù)將一個(gè)事件對(duì)象重置為無(wú)信號(hào)狀態(tài)。 BOOLPlusEvent(HANDLEhEvent);最后,使用CloseHandle銷毀創(chuàng)建的事件對(duì)象。11.6.4信號(hào)量對(duì)象在線程之間進(jìn)行同步的原因大致有兩個(gè):一個(gè)是由于線程之間競(jìng)爭(zhēng)共享的資源,一個(gè)是為了完成某種任務(wù)而協(xié)作。通過(guò)互斥可以實(shí)現(xiàn)線程之間由于競(jìng)爭(zhēng)所需要的同步,通過(guò)事件可以實(shí)現(xiàn)線程之間由于協(xié)作而需要的同步。原則上講,使用互斥量和事件可以解決所有線程之間的同步問(wèn)題。而信號(hào)量很好的將互斥量和事件結(jié)合起來(lái),同時(shí)解決了線程的競(jìng)爭(zhēng)和協(xié)作的問(wèn)題。它是對(duì)事件同步的推廣——在信號(hào)量之中有一個(gè)內(nèi)置的計(jì)數(shù)值,用于對(duì)資源進(jìn)行計(jì)數(shù)。同時(shí)它通過(guò)內(nèi)置的互斥機(jī)制保證在有多個(gè)線程試圖對(duì)計(jì)數(shù)值進(jìn)行修改時(shí),在任何一個(gè)時(shí)刻只有一個(gè)線程對(duì)計(jì)數(shù)值進(jìn)行修改。11.6.4信號(hào)量對(duì)象(續(xù))創(chuàng)建和打開(kāi)信號(hào)量對(duì)象: 首先在使用信號(hào)量對(duì)象,必須調(diào)用函數(shù)CreateSemaphore創(chuàng)建它。 HANDLECreateSemaphore( LPSECURITY_ATTRIBUTESlpSemaphoreAttributes, BOOLbInitialCount LONGlMaximumCount; LPCSTRlpName }11.6.4信號(hào)量對(duì)象(續(xù))可以調(diào)用函數(shù)OpenSemaphore來(lái)獲得信號(hào)量句柄: HANDLEOpenSemaphore{ DWORDwDesiredAccess, BOOLbInitialHandle; LPCSTRlpName };獲得和釋放信號(hào)量, BOOLRealseSemaphore{ HANDLEhSemaphore, LONGlRealseCount, LPLONGlpPreviousCount, };當(dāng)這個(gè)信號(hào)量對(duì)象不再需要時(shí),就應(yīng)該調(diào)用函數(shù)CloseHandle來(lái)釋放這個(gè)信號(hào)量對(duì)象,從內(nèi)存中消除。11.6.5各種同步方法的比較 本章講述了四種線程同步方法,它們分別使互斥量,臨界段,事件和信號(hào)量,這些方法有各自的特點(diǎn),用于不同的場(chǎng)合。下面比較一下這些方法的異同:互斥量、事件和信號(hào)量都是內(nèi)核對(duì)象,可用于進(jìn)程之間的同步;臨界段是進(jìn)程內(nèi)對(duì)象只能用于線程之間的同步。雖然在一個(gè)進(jìn)程內(nèi)實(shí)現(xiàn)同步時(shí),臨界段對(duì)象和互斥量相似,但是在性能上臨界段對(duì)象要優(yōu)于互斥量。事件和其他幾個(gè)同步方法的不同在于事件的主要作用不是保護(hù)進(jìn)程共享資源,而是用于等待某個(gè)事件和特定事件發(fā)生時(shí)發(fā)送信號(hào),以協(xié)調(diào)線程之間的動(dòng)作。信號(hào)量和其他同步方法的區(qū)別在于它允許一個(gè)以上的線程同時(shí)訪問(wèn)共享的資源,而其他同步的方法都保證同時(shí)只能有一個(gè)線程訪問(wèn)共享的資源。信號(hào)量的主要功能在于用于資源計(jì)數(shù)。同步方法的選擇要根據(jù)應(yīng)用場(chǎng)合、同步目的和各種同步對(duì)象各自的特點(diǎn)來(lái)選擇,下面介紹選擇同步方法的一些原則,可以根據(jù)這些原則來(lái)選擇同步對(duì)象:首先線程在訪問(wèn)共享資源之前是否要等待某個(gè)事件的發(fā)生。比如,在線程訪問(wèn)一個(gè)共享文件前是否要從通信端口接收信息。如果是這樣,就可以用事件同步;在一個(gè)應(yīng)用程序中是否有多個(gè)線程可以同時(shí)訪問(wèn)的共享資源,如果是則選擇信號(hào)量;是否有多個(gè)進(jìn)程使用共享資源,如果是則選擇互斥量;如果以上條件都不滿足,則使用臨界段就可以了。11.7應(yīng)用實(shí)例排火車的游戲大家都玩過(guò)吧?其規(guī)則是這樣的:將撲克牌分成兩份,每人拿一份,二人輪流出牌。如果你出的牌和前面的某張牌一樣(不區(qū)分花色),則從那張一樣的牌到你出的牌都被你拿走,這樣輪流出牌,直到其中一人的牌出完為止。最后手上有牌的一方為勝,圖11.1。在這個(gè)程序中要用到事件同步。因?yàn)槿撕陀?jì)算機(jī)不能同時(shí)出牌。比較合理的做法是人出完牌后通知計(jì)算機(jī),然后計(jì)算機(jī)出牌,計(jì)算機(jī)出完牌之后通知人,計(jì)算機(jī)處于等待狀態(tài)。11.7應(yīng)用實(shí)例(續(xù)) 首先創(chuàng)建基于對(duì)話框工程Eg11_1:1.在VC++集成開(kāi)發(fā)環(huán)境中,通過(guò)菜單File|New,彈出New對(duì)話框;2.在Projects選項(xiàng)卡中選擇MFCAppWizard(exe),在Projectname中輸入“Eg11_1”Location讀者可以自己選擇;3.按下OK按鈕,在彈出的MFCAppWizardStep-1對(duì)話框中選擇程序框架為單文檔框架,即選中SingleDocument;4.一直接受默認(rèn)選項(xiàng),直到MFCAppWizardStep-6,把CEg11_1View類的基類選擇為CFormView。如圖11.2所示。5.按下“Finish”按鈕,在彈出的NewProjectInformation對(duì)話框中按下“OK”按鈕后等待創(chuàng)建完相應(yīng)的工程。11.7.1用戶界面的設(shè)計(jì)可以參照?qǐng)D11.1和表11.2來(lái)設(shè)計(jì)界面11.7.2新增成員變量及初始化在CEg11_1View.h中增加一些新的變量:public: CEg11_1Doc*GetDocument();
//事件對(duì)象,表示計(jì)算機(jī)出牌完成,等待游戲者出牌CEventm_computerready; //事件對(duì)象,表示游戲者出牌完成,等待計(jì)算機(jī)出牌 CEventm_playerready; //游戲正在進(jìn)行的標(biāo)志 BOOLm_playing; //當(dāng)前牌局中牌的張數(shù) intm_cardnum; //當(dāng)前計(jì)算機(jī)成績(jī)即計(jì)算機(jī)牌的張數(shù) intm_computernum; //當(dāng)前游戲者牌的牌的張數(shù) intm_playernum; //當(dāng)前牌局 intm_card[100];11.7.2新增成員變量及初始化(續(xù))在構(gòu)造函數(shù)中初始化事件對(duì)象和其他變量:CEg11_1View::CEg11_1View() :CFormView(CEg11_1View::IDD),m_computerready(TRUE),m_playerready(FALSE){ //{{AFX_DATA_INIT(CEg11_1View) //NOTE:theClassWizardwilladdmemberinitializationhere //}}AFX_DATA_INIT //TODO:addconstructioncodeherem_playing=false;m_cardnum=0;m_computernum=24;m_playernum=24;}11.7.2新增成員變量及初始化(續(xù))通過(guò)ClassWizard添加成員函數(shù)OnInitialUpdate(),重載這個(gè)函數(shù)如下:voidCEg11_1View::OnInitialUpdate(){ CFormView::OnInitialUpdate(); GetParentFrame()->RecalcLayout(); ResizeParentToFit();
GetDlgItem(IDC_DISCARD)->EnableWindow(FALSE); SetDlgItemText(IDC_STATIC_SCORE1,"24"); SetDlgItemText(IDC_STATIC_SCORE2,"24");}11.7.3創(chuàng)建菜單響應(yīng)函數(shù)通過(guò)ClassWizard為菜單ID_FILE_BEGIN和ID_FILE_END添加菜單響應(yīng)函數(shù),接受系統(tǒng)默認(rèn)的函數(shù)名,編輯函數(shù)代碼如下:voidCEg11_1View::OnFileBegin(){ //TODO:Addyourcommandhandlercodehere
m_playing=true; //啟動(dòng)計(jì)算機(jī)出牌線程和游戲者線程 AfxBeginThread(CompThread,(void*)this); AfxBeginThread(PlayerThread,(void*)this);
}voidCEg11_1View::OnFileEnd(){ //TODO:Addyourcommandhandlercodehere
exit(0
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 九年級(jí)數(shù)學(xué)下冊(cè)第26章概率初步26.2等可能情形下的概率計(jì)算第2課時(shí)用樹(shù)狀圖或列表法求概率教案新版滬科版
- 2024-2025學(xué)年新教材高中語(yǔ)文第一單元3別了“不列顛尼亞”縣委書(shū)記的榜樣-焦裕祿達(dá)標(biāo)練習(xí)含解析新人教版選擇性必修上冊(cè)
- 2024高考?xì)v史一輪復(fù)習(xí)單元質(zhì)檢二西方民主政治及科學(xué)社會(huì)主義的理論和實(shí)踐含解析新人教版
- 四年級(jí)語(yǔ)文楚才杯尷尬12
- 2024?2025學(xué)年高一上學(xué)期期中考試數(shù)學(xué)試題含答案
- 物聯(lián)網(wǎng)技術(shù)應(yīng)用與推廣合作協(xié)議
- Primulic-acid-I-Standard-生命科學(xué)試劑-MCE
- 動(dòng)植物分類教學(xué)設(shè)計(jì)計(jì)劃
- 班級(jí)旅游與社交技能培養(yǎng)計(jì)劃
- 2024年國(guó)際版權(quán)交易許可合同
- 明挖隧道施工方案
- 大水學(xué)校德育活動(dòng)記錄
- 消防部隊(duì)水源手冊(cè)范本
- 政策工具視角下的中國(guó)教育扶貧政策文本研究
- 教育部新版本科專業(yè)目錄(2012年)
- 七年級(jí)英語(yǔ)上培優(yōu)扶差記錄表
- 二級(jí)減速器箱體蓋工藝卡片
- 互聯(lián)網(wǎng)高速專線電路開(kāi)通測(cè)試報(bào)告[寶典]
- 乳頭溢液的診斷及處理ppt課件
- 虎牌電飯煲中文使用說(shuō)明書(shū)
- 《相信自己,我是最棒的》主題班會(huì)說(shuō)課稿
評(píng)論
0/150
提交評(píng)論