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