多线程编程之二——MFC中的多线程开发
五、MFC對多線程編程的支持
MFC中有兩類線程,分別稱之為工作者線程和用戶界面線程。二者的主要區(qū)別在于工作者線程沒有消息循環(huán),而用戶界面線程有自己的消息隊列和消息循環(huán)。
工作者線程沒有消息機制,通常用來執(zhí)行后臺計算和維護(hù)任務(wù),如冗長的計算過程,打印機的后臺打印等。用戶界面線程一般用于處理獨立于其他線程執(zhí)行之外的用戶輸入,響應(yīng)用戶及系統(tǒng)所產(chǎn)生的事件和消息等。但對于Win32的API編程而言,這兩種線程是沒有區(qū)別的,它們都只需線程的啟動地址即可啟動線程來執(zhí)行任務(wù)。
在MFC中,一般用全局函數(shù)AfxBeginThread()來創(chuàng)建并初始化一個線程的運行,該函數(shù)有兩種重載形式,分別用于創(chuàng)建工作者線程和用戶界面線程。兩種重載函數(shù)原型和參數(shù)分別說明如下:
PfnThreadProc:指向工作者線程的執(zhí)行函數(shù)的指針,線程函數(shù)原型必須聲明如下:
UINT ExecutingFunction(LPVOID pParam);請注意,ExecutingFunction()應(yīng)返回一個UINT類型的值,用以指明該函數(shù)結(jié)束的原因。一般情況下,返回0表明執(zhí)行成功。
- pParam:傳遞給線程函數(shù)的一個32位參數(shù),執(zhí)行函數(shù)將用某種方式解釋該值。它可以是數(shù)值,或是指向一個結(jié)構(gòu)的指針,甚至可以被忽略;
- nPriority:線程的優(yōu)先級。如果為0,則線程與其父線程具有相同的優(yōu)先級;
- nStackSize:線程為自己分配堆棧的大小,其單位為字節(jié)。如果nStackSize被設(shè)為0,則線程的堆棧被設(shè)置成與父線程堆棧相同大小;
- dwCreateFlags:如果為0,則線程在創(chuàng)建后立刻開始執(zhí)行。如果為CREATE_SUSPEND,則線程在創(chuàng)建后立刻被掛起;
- lpSecurityAttrs:線程的安全屬性指針,一般為NULL;
?
pThreadClass 是指向 CWinThread 的一個導(dǎo)出類的運行時類對象的指針,該導(dǎo)出類定義了被創(chuàng)建的用戶界面線程的啟動、退出等;其它參數(shù)的意義同形式1。使用函數(shù)的這個原型生成的線程也有消息機制,在以后的例子中我們將發(fā)現(xiàn)同主線程的機制幾乎一樣。
下面我們對CWinThread類的數(shù)據(jù)成員及常用函數(shù)進(jìn)行簡要說明。
- m_hThread:當(dāng)前線程的句柄;
- m_nThreadID:當(dāng)前線程的ID;
- m_pMainWnd:指向應(yīng)用程序主窗口的指針
該函數(shù)中的dwCreateFlags、nStackSize、lpSecurityAttrs參數(shù)和API函數(shù)CreateThread中的對應(yīng)參數(shù)有相同含義,該函數(shù)執(zhí)行成功,返回非0值,否則返回0。
一般情況下,調(diào)用AfxBeginThread()來一次性地創(chuàng)建并啟動一個線程,但是也可以通過兩步法來創(chuàng)建線程:首先創(chuàng)建CWinThread類的一個對象,然后調(diào)用該對象的成員函數(shù)CreateThread()來啟動該線程。
重載該函數(shù)以控制用戶界面線程實例的初始化。初始化成功則返回非0值,否則返回0。用戶界面線程經(jīng)常重載該函數(shù),工作者線程一般不使用InitInstance()。
virtual int CWinThread::ExitInstance();在線程終結(jié)前重載該函數(shù)進(jìn)行一些必要的清理工作。該函數(shù)返回線程的退出碼,0表示執(zhí)行成功,非0值用來標(biāo)識各種錯誤。同InitInstance()成員函數(shù)一樣,該函數(shù)也只適用于用戶界面線程。
六、MFC多線程編程實例
在Visual C++ 6.0編程環(huán)境中,我們既可以編寫C風(fēng)格的32位Win32應(yīng)用程序,也可以利用MFC類庫編寫C++風(fēng)格的應(yīng)用程序,二者各有其優(yōu)缺點?;赪in32的應(yīng)用程序執(zhí)行代碼小巧,運行效率高,但要求程序員編寫的代碼較多,且需要管理系統(tǒng)提供給程序的所有資源;而基于MFC類庫的應(yīng)用程序可以快速建立起應(yīng)用程序,類庫為程序員提供了大量的封裝類,而且Developer Studio為程序員提供了一些工具來管理用戶源程序,其缺點是類庫代碼很龐大。由于使用類庫所帶來的快速、簡捷和功能強大等優(yōu)越性,因此除非有特殊的需要,否則Visual C++推薦使用MFC類庫進(jìn)行程序開發(fā)。
我們知道,MFC中的線程分為兩種:用戶界面線程和工作者線程。我們將分別舉例說明。
用 MFC 類庫編程實現(xiàn)工作者線程
例程5 MultiThread5
為了與Win32 API對照,我們使用MFC 類庫編程實現(xiàn)例程3 MultiThread3。
注意,二者應(yīng)在類CMultiThread5Dlg的外部。
在類CMultiThread5Dlg內(nèi)部添加protected型變量:
雙擊按鈕IDC_START,添加相應(yīng)消息處理函數(shù):
void CMultiThread5Dlg::OnStart() {// TODO: Add your control notification handler code hereUpdateData(TRUE);Info.nMilliSecond=m_nMilliSecond;Info.pctrlProgress=&m_ctrlProgress;pThread=AfxBeginThread(ThreadFunc,&Info);} 在函數(shù)BOOL CMultiThread3Dlg::OnInitDialog()中添加語句: {……// TODO: Add extra initialization herem_ctrlProgress.SetRange(0,99);m_nMilliSecond=10;UpdateData(FALSE);return TRUE; // return TRUE unless you set the focus to a control} 添加線程處理函數(shù): UINT ThreadFunc(LPVOID lpParam){threadInfo* pInfo=(threadInfo*)lpParam;for(int i=0;i<100;i++){int nTemp=pInfo->nMilliSecond;pInfo->pctrlProgress->SetPos(i);Sleep(nTemp);}return 0;}用 MFC 類庫編程實現(xiàn)用戶界面線程
創(chuàng)建用戶界面線程的步驟:
A、在UIThreadDlg.cpp的開頭加入語句: #include "UIThread.h" B、把UIThread.h中類CUIThread()的構(gòu)造函數(shù)的特性由 protected 改為 public。
用戶界面線程的執(zhí)行次序與應(yīng)用程序主線程相同,首先調(diào)用用戶界面線程類的InitInstance()函數(shù),如果返回TRUE,繼續(xù)調(diào)用線程的Run()函數(shù),該函數(shù)的作用是運行一個標(biāo)準(zhǔn)的消息循環(huán),并且當(dāng)收到WM_QUIT消息后中斷,在消息循環(huán)過程中,Run()函數(shù)檢測到線程空閑時(沒有消息),也將調(diào)用OnIdle()函數(shù),最后Run()函數(shù)返回,MFC調(diào)用ExitInstance()函數(shù)清理資源。
你可以創(chuàng)建一個沒有界面而有消息循環(huán)的線程,例如:你可以從CWinThread派生一個新類,在InitInstance函數(shù)中完成某項任務(wù)并返回FALSE,這表示僅執(zhí)行InitInstance函數(shù)中的任務(wù)而不執(zhí)行消息循環(huán),你可以通過這種方法,完成一個工作者線程的功能。
例程6 MultiThread6
好了,編譯并運行程序吧。每單擊一次“用戶界面線程”按鈕,都會彈出一個線程對話框,在任何一個線程對話框內(nèi)按下鼠標(biāo)左鍵,都會彈出一個消息框。
總結(jié)
以上是生活随笔為你收集整理的多线程编程之二——MFC中的多线程开发的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php ai库,收藏 | 深度学习框架、
- 下一篇: 数字时钟html5 js,html5 c