摘要:本文主要以MFC多線(xiàn)程為中心,分別對(duì)MFC多線(xiàn)程的實(shí)例、MFC多線(xiàn)程之間的通信展開(kāi)的一系列研究,下面我們來(lái)看看原文。
一、多線(xiàn)程概述
進(jìn)程和線(xiàn)程都是操作系統(tǒng)的概念。進(jìn)程是應(yīng)用程序的執(zhí)行實(shí)例,每個(gè)進(jìn)程是由私有的虛擬地址空間、代碼、數(shù)據(jù)和其它各種系統(tǒng)資源組成,進(jìn)程在運(yùn)行過(guò)程中創(chuàng)建的資源隨著進(jìn)程的終止而被銷(xiāo)毀,所使用的系統(tǒng)資源在進(jìn)程終止時(shí)被釋放或關(guān)閉。
線(xiàn)程是進(jìn)程內(nèi)部的一個(gè)執(zhí)行單元。系統(tǒng)創(chuàng)建好進(jìn)程后,實(shí)際上就啟動(dòng)執(zhí)行了該進(jìn)程的主執(zhí)行線(xiàn)程,主執(zhí)行線(xiàn)程以函數(shù)地址形式,比如說(shuō)main或WinMain函數(shù),將程序的啟動(dòng)點(diǎn)提供給Windows系統(tǒng)。主執(zhí)行線(xiàn)程終止了,進(jìn)程也就隨之終止。
每一個(gè)進(jìn)程至少有一個(gè)主執(zhí)行線(xiàn)程,它無(wú)需由用戶(hù)去主動(dòng)創(chuàng)建,是由系統(tǒng)自動(dòng)創(chuàng)建的。用戶(hù)根據(jù)需要在應(yīng)用程序中創(chuàng)建其它線(xiàn)程,多個(gè)線(xiàn)程并發(fā)地運(yùn)行于同一個(gè)進(jìn) 程中。一個(gè)進(jìn)程中的所有線(xiàn)程都在該進(jìn)程的虛擬地址空間中,共同使用這些虛擬地址空間、全局變量和系統(tǒng)資源,所以線(xiàn)程間的通訊非常方便,多線(xiàn)程技術(shù)的應(yīng)用也 較為廣泛。
多線(xiàn)程可以實(shí)現(xiàn)并行處理,避免了某項(xiàng)任務(wù)長(zhǎng)時(shí)間占用CPU時(shí)間。要說(shuō)明的一點(diǎn)是,目前大多數(shù)的計(jì)算機(jī)都是單處理器(CPU)的,為了運(yùn)行所有這些線(xiàn)程, 操作系統(tǒng)為每個(gè)獨(dú)立線(xiàn)程安排一些CPU時(shí)間,操作系統(tǒng)以輪換方式向線(xiàn)程提供時(shí)間片,這就給人一種假象,好象這些線(xiàn)程都在同時(shí)運(yùn)行。由此可見(jiàn),如果兩個(gè)非常 活躍的線(xiàn)程為了搶奪對(duì)CPU的控制權(quán),在線(xiàn)程切換時(shí)會(huì)消耗很多的CPU資源,反而會(huì)降低系統(tǒng)的性能。這一點(diǎn)在多線(xiàn)程編程時(shí)應(yīng)該注意。
二、MFC對(duì)多線(xiàn)程編程的支持
MFC中有兩類(lèi)線(xiàn)程,分別稱(chēng)之為工作者線(xiàn)程和用戶(hù)界面線(xiàn)程。二者的主要區(qū)別在于工作者線(xiàn)程沒(méi)有消息循環(huán),而用戶(hù)界面線(xiàn)程有自己的消息隊(duì)列和消息循環(huán)。
工作者線(xiàn)程沒(méi)有消息機(jī)制,通常用來(lái)執(zhí)行后臺(tái)計(jì)算和維護(hù)任務(wù),如冗長(zhǎng)的計(jì)算過(guò)程,打印機(jī)的后臺(tái)打印等。用戶(hù)界面線(xiàn)程一般用于處理獨(dú)立于其他線(xiàn)程執(zhí)行之外的用戶(hù)輸入,響應(yīng)用戶(hù)及系統(tǒng)所產(chǎn)生的事件和消息等。但對(duì)于Win32的API編程而言,這兩種線(xiàn)程是沒(méi)有區(qū)別的,它們都只需線(xiàn)程的啟動(dòng)地址即可啟動(dòng)線(xiàn)程來(lái)執(zhí)行任務(wù)。
在MFC中,一般用全局函數(shù)AfxBeginThread()來(lái)創(chuàng)建并初始化一個(gè)線(xiàn)程的運(yùn)行,該函數(shù)有兩種重載形式,分別用于創(chuàng)建工作者線(xiàn)程和用戶(hù)界面線(xiàn)程。兩種重載函數(shù)原型和參數(shù)分別說(shuō)明如下:
(1) CWinThread* AfxBeginThread(AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
nPriority=THREAD_PRIORITY_NORMAL,
UINT nStackSize=0,
DWORD dwCreateFlags=0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);
PfnThreadProc:指向工作者線(xiàn)程的執(zhí)行函數(shù)的指針,線(xiàn)程函數(shù)原型必須聲明如下: UINT ExecutingFunction(LPVOID pParam);
請(qǐng)注意,ExecutingFunction()應(yīng)返回一個(gè)UINT類(lèi)型的值,用以指明該函數(shù)結(jié)束的原因。一般情況下,返回0表明執(zhí)行成功。
pParam:傳遞給線(xiàn)程函數(shù)的一個(gè)32位參數(shù),執(zhí)行函數(shù)將用某種方式解釋該值。它可以是數(shù)值,或是指向一個(gè)結(jié)構(gòu)的指針,甚至可以被忽略;
nPriority:線(xiàn)程的優(yōu)先級(jí)。如果為0,則線(xiàn)程與其父線(xiàn)程具有相同的優(yōu)先級(jí);
nStackSize:線(xiàn)程為自己分配堆棧的大小,其單位為字節(jié)。如果 nStackSize被設(shè)為0,則線(xiàn)程的堆棧被設(shè)置成與父線(xiàn)程堆棧相同大小;
dwCreateFlags:如果為0,則線(xiàn)程在創(chuàng)建后立刻開(kāi)始執(zhí)行。如果為CREATE_SUSPEND,則線(xiàn)程在創(chuàng)建后立刻被掛起;
lpSecurityAttrs:線(xiàn)程的安全屬性指針,一般為 NULL;
(2) CWinThread* AfxBeginThread(CRuntimeClass* pThreadClass,
int nPriority=THREAD_PRIORITY_NORMAL,
UINT nStackSize=0,
DWORD dwCreateFlags=0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);
pThreadClass 是指向 CWinThread 的一個(gè)導(dǎo)出類(lèi)的運(yùn)行時(shí)類(lèi)對(duì)象的指針,該導(dǎo)出類(lèi)定義了被創(chuàng)建的用戶(hù)界面線(xiàn)程的啟動(dòng)、退出等;其它參數(shù)的意義同形式1。使用函數(shù)的這個(gè)原型生成的線(xiàn)程也有消息機(jī)制,在以后的例子中我們將發(fā)現(xiàn)同主線(xiàn)程的機(jī)制幾乎一樣。
下面我們對(duì)CWinThread類(lèi)的數(shù)據(jù)成員及常用函數(shù)進(jìn)行簡(jiǎn)要說(shuō)明。
m_hThread:當(dāng)前線(xiàn)程的句柄;
m_nThreadID:當(dāng)前線(xiàn)程的ID;
m_pMainWnd:指向應(yīng)用程序主窗口的指針
BOOL CWinThread::CreateThread(DWORD dwCreateFlags=0,
UINT nStackSize=0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);
該函數(shù)中的dwCreateFlags、nStackSize、lpSecurityAttrs參數(shù)和API函數(shù)CreateThread中的對(duì)應(yīng)參數(shù)有相同含義,該函數(shù)執(zhí)行成功,返回非0值,否則返回0。
一般情況下,調(diào)用AfxBeginThread()來(lái)一次性地創(chuàng)建并啟動(dòng)一個(gè)線(xiàn)程,但是也可以通過(guò)兩步法來(lái)創(chuàng)建線(xiàn)程:首先創(chuàng)建CWinThread類(lèi)的一個(gè)對(duì)象,然后調(diào)用該對(duì)象的成員函數(shù)CreateThread()來(lái)啟動(dòng)該線(xiàn)程。
virtual BOOL CWinThread::InitInstance();
重載該函數(shù)以控制用戶(hù)界面線(xiàn)程實(shí)例的初始化。初始化成功則返回非0值,否則返回0。用戶(hù)界面線(xiàn)程經(jīng)常重載該函數(shù),工作者線(xiàn)程一般不使用 InitInstance()。 virtual int CWinThread::ExitInstance();
在線(xiàn)程終結(jié)前重載該函數(shù)進(jìn)行一些必要的清理工作。該函數(shù)返回線(xiàn)程的退出碼,0表示執(zhí)行成功,非0值用來(lái)標(biāo)識(shí)各種錯(cuò)誤。同 InitInstance()成員函數(shù)一樣,該函數(shù)也只適用于用戶(hù)界面線(xiàn)程。
評(píng)論
查看更多