在MFC里面实现线程的实例
線程是一種從軟件到硬件的技術(shù),主要目的是為了提高運(yùn)行速度,和多任務(wù)。
××××××××××××××××××××××××××××××××××××需要儲(chǔ)備的資料(他人的)××××××××××××××××××××××××××××?
××http://haobinnan.blog.51cto.com/775253/658446
多線程概述
?
?
???????? 進(jìn)程和線程都是操作系統(tǒng)的概念。進(jìn)程是在基于內(nèi)存的概念,線程是基于CPU的概念。CPU不清楚什么玩意叫進(jìn)程,CPU處理的任務(wù)叫線程。一個(gè)進(jìn)程可以劃分成多個(gè)線程給CPU處理。一個(gè)程序可以有多個(gè)進(jìn)程 用于處理不同的事情。
?
? ? ? ? ? 進(jìn)程是應(yīng)用程序的執(zhí)行實(shí)例,每個(gè)進(jìn)程是由私有的虛擬地址空間、代碼、數(shù)據(jù)和其它各種系統(tǒng)資源組成,進(jìn)程在運(yùn)行過程中創(chuàng)建的資源隨著進(jìn)程的終止而被銷毀,所使用的系統(tǒng)資源在進(jìn)程終止時(shí)被釋放或關(guān)閉。
?
???????? 線程是進(jìn)程內(nèi)部的一個(gè)執(zhí)行單元,系統(tǒng)創(chuàng)建好進(jìn)程后,實(shí)際上就啟動(dòng)執(zhí)行了該進(jìn)程的主執(zhí)行線程,主執(zhí)行線程以函數(shù)地址形式,比如說main或WinMain函數(shù),將程序的啟動(dòng)點(diǎn)提供給Windows系統(tǒng)。主執(zhí)行線程終止了,進(jìn)程也就隨之終止。
?
???????? 每一個(gè)進(jìn)程至少有一個(gè)主執(zhí)行線程,它無需由用戶去主動(dòng)創(chuàng)建,是由系統(tǒng)自動(dòng)創(chuàng)建的。用戶根據(jù)需要在應(yīng)用程序中創(chuàng)建其它線程,多個(gè)線程并發(fā)地運(yùn)行于同一個(gè)進(jìn)程中。一個(gè)進(jìn)程中的所有線程都在該進(jìn)程的虛擬地址空間中,共同使用這些虛擬地址空間、全局變量和系統(tǒng)資源,所以線程間的通訊非常方便,多線程技術(shù)的應(yīng)用也較為廣泛。
?
???????? MFC中有兩類線程,分別稱之為工作者線程和用戶界面線程。二者的主要區(qū)別在于工作者線程沒有消息循環(huán),而用戶界面線程有自己的消息隊(duì)列和消息循環(huán)。
???????? 在MFC中,一般用全局函數(shù)AfxBeginThread()來創(chuàng)建并初始化一個(gè)線程的運(yùn)行,該函數(shù)有兩種重載形式,(為啥叫重載形式呢?因?yàn)橄到y(tǒng)中已經(jīng)有了這兩個(gè)函數(shù),在使用的使用給予不同的變量不就是重載的定義嗎??是的)分別用于創(chuàng)建工作者線程和用戶界面線程。兩種重載函數(shù)原型和參數(shù)分別說明如下:?
CreateThread是一個(gè)API,而AfxBeginThread是MFC中的一個(gè)函數(shù)。后者在內(nèi)部調(diào)用了前者。
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
? ? 對(duì)于工作線程來說,啟動(dòng)一個(gè)線程,首先需要編寫一個(gè)希望與應(yīng)用程序的其余部分并行運(yùn)行的函數(shù)如Fun1(),
接著定義一個(gè)指向CwinThread對(duì)象的指針變量*pThread,(在MFC中可以用App)
調(diào)用AfxBeginThread(Fun1,param,priority)函數(shù),返回值付給pThread變量的同時(shí)一并啟動(dòng)該線程來執(zhí)行上面的Fun1()函數(shù),
其中Fun1是線程要運(yùn)行的函數(shù)的名字,也既是上面所說的控制函數(shù)的名字,param是準(zhǔn)備傳送給線程函數(shù)?Fun1的任意32位值,
priority則是定義該線程的優(yōu)先級(jí)別,它是預(yù)定義的常數(shù)。
線程函數(shù)是回調(diào)函數(shù),線程函數(shù)在類內(nèi)必須是靜態(tài)成員函數(shù),或者是類外聲明的全局函數(shù)。
因?yàn)殪o態(tài)成員函數(shù)不能訪問類的非靜態(tài)成員函數(shù),所以在線程函數(shù)中要定義一個(gè)類的指針指向this指針,就可以用類的指針來調(diào)用類的成員函數(shù)。
數(shù)據(jù)傳遞使用this處理。
?
無HMI ?WORK線程 ??
CWinThread* AfxBeginThread(
? ? ? ? ? ? ? ? ? ? ? ?AFX_THREADPROC pfnThreadProc,//指向工作者線程的執(zhí)行函數(shù)的指針,線程函數(shù)原型必須聲明如下:?UINTExecutingFunction(LPVOID pParam);
??????????????????????? LPVOID pParam,/**///傳遞給線程函數(shù)的一個(gè)32位參數(shù),執(zhí)行函數(shù)將用某種方式解釋該值。它可以是數(shù)值,或是指向一個(gè)結(jié)構(gòu)的指針,甚至可以被忽略;
??????????????????????nPriority=THREAD_PRIORITY_NORMAL,//線程的優(yōu)先級(jí)。如果為0,則線程與其父線程具有相同的優(yōu)先級(jí);
?????????????????????? UINTnStackSize=0,//線程為自己分配堆棧的大小,其單位為字節(jié)。如果nStackSize被設(shè)為0,則線程的堆棧被設(shè)置成與父線程堆棧相同大小;
?????????????????????? DWORDdwCreateFlags=0,//如果為0,則線程在創(chuàng)建后立刻開始執(zhí)行。如果為CREATE_SUSPEND,則線程在創(chuàng)建后立刻被掛起;
??????????????????????LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL//線程的安全屬性指針,一般為NULL;
);
?
?
一個(gè)工作線程創(chuàng)建的實(shí)例: 環(huán)境是VS2010 ?MFC ?Win7 ?64位系統(tǒng)。
?
<span style="background-color: rgb(0, 204, 204);">public://工作線程創(chuàng)建第一步:在某個(gè)頭文件里面聲明一個(gè)函數(shù)。static UINT Scada_Operational(LPVOID pParam);int aaa; };extern CTestApp theApp; </span>×××
?
?
<span style="background-color: rgb(0, 204, 204);">//工作線程創(chuàng)建第二步:在對(duì)應(yīng)的實(shí)現(xiàn)文件里面,定義這個(gè)函數(shù)。 UINT CTestApp::Scada_Operational(LPVOID pParam) {Sleep(1000);AfxMessageBox(_T("準(zhǔn)備賦值"));CTestApp* theApp = (CTestApp*)pParam;int bb=0;bb= theApp->aaa;Sleep(1000);AfxMessageBox(_T("完成賦值"));return 0; }</span>
×××
?
?
<span style="background-color: rgb(0, 204, 204);">//工作線程創(chuàng)建第三步:使用MFC特有的函數(shù)AfxBeginThread 將函數(shù)變?yōu)榫€程。AfxBeginThread(Scada_Operational,this);</span>源代碼:http://pan.baidu.com/s/1mgrAxVM
×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
?
?
??UI線程
創(chuàng)建一個(gè)用戶界面線程,首先要從類CwinThread產(chǎn)生一個(gè)派生類,同時(shí)必須使用DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE來聲明和實(shí)現(xiàn)這個(gè)CwinThread派生類。
第二步是根據(jù)需要重載該派生類的一些成員函數(shù)如:ExitInstance();InitInstance();OnIdle();?PreTranslateMessage()等函數(shù),最后啟動(dòng)該用戶界面線程,調(diào)用AfxBeginThread()函數(shù)的一個(gè)版 ? 本:
CWinThread*AfxBeginThread(
?
CRuntimeClass* pThreadClass,//從CWinThread派生的RUNTIME_CLASS類;
?????????????????????? intnPriority=THREAD_PRIORITY_NORMAL,//線程優(yōu)先級(jí),如果為0,則與創(chuàng)建該線程的線程相同;
?????????????????????? UINT nStackSize=0,//線程的堆棧大小,如果為0,則與創(chuàng)建該線程的線程相同;
?????????????????????? DWORD dwCreateFlags=0,//一個(gè)創(chuàng)建標(biāo)識(shí),如果是CREATE_SUSPENDED,
則在懸掛狀態(tài)創(chuàng)建線程,在線程創(chuàng)建后線程掛起,否則線程在創(chuàng)建后開始線程的執(zhí)行。
?????????????????????? LPSECURITY_ATTRIBUTESlpSecurityAttrs=NULL//線程的安全屬性,NT下有用。
);
?范例 :
?
1、建立一個(gè)基于MFC的對(duì)話框應(yīng)用程序。
2、向程序中添加一個(gè)以CWinThread為基類的新類CUIThread,該類用于啟動(dòng)一個(gè)用戶界面線程。
3、向程序中添加一個(gè)對(duì)話框資源,并建立相應(yīng)的對(duì)話框類CUIThreadDlg,這個(gè)對(duì)話框的基類是CDialogEx。
? ? 該對(duì)話框?qū)⒈蛔鳛橛脩艚缑婢€程的主窗口。
4、在UIThread.h中加入#include "UIThreadDlg.h"和
并在CUIThread::InitInstance()中加入
BOOL CUIThread::InitInstance() {// TODO: 在此執(zhí)行任意逐線程初始化//用戶線程第六步:添加創(chuàng)建程序m_pMainWnd = &m_dlg;m_dlg.DoModal();;return TRUE; }
5、CUIThread::InitInstance()中創(chuàng)建的CUIThreadDlg將與主窗口在獨(dú)立的線程中運(yùn)行,可以在CUIThreadDlg中加入各種執(zhí)行耗時(shí)任務(wù)的代碼而不會(huì)影響主窗口的運(yùn)行。
6、在 原始對(duì)話框上面添加一個(gè)按鈕 并創(chuàng)建點(diǎn)擊事件響應(yīng)函數(shù),
//用戶線程第七步:添加線程的頭文件#include "UIThread.h"。
在函數(shù)中添加線程創(chuàng)建
void CTestGszDlg::OnBnClickedButton1() {// TODO: 在此添加控件通知處理程序代碼//CWinThread* p = AfxBeginThread(RUNTIME_CLASS(CUIThread));//用戶線程第八步:正式創(chuàng)建線程AfxBeginThread(RUNTIME_CLASS(CUIThread)); }?
7:我們創(chuàng)建的線程在結(jié)束的時(shí)候 銷毀我們新建的對(duì)話框
int CUIThread::ExitInstance()
{
? ? m_dlg.DestroyWindow();
? ? return CWinThread::ExitInstance();
}
配套源代碼:http://pan.baidu.com/s/1jGzLTye
××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××
幾個(gè)常用的配套函數(shù)
?
?
//獲取線程對(duì)象
CWinThread*?AFXAPIAfxGetThread();
//獲取當(dāng)前消息
MSG*?AFXAPIAfxGetCurrentMessage();
//結(jié)束線程執(zhí)行
void?AFXAPIAfxEndThread(UINTnExitCode,BOOLbDelete?=TRUE);
//初始化線程
void?AFXAPIAfxInitThread();
//終止線程執(zhí)行
void?AFXAPIAfxTermThread(HINSTANCEhInstTerm?=NULL);
總結(jié)
以上是生活随笔為你收集整理的在MFC里面实现线程的实例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MFC的Serialize机制及其使用(
- 下一篇: x264_param_t结构体参数分析