線程是一種從軟件到硬件的技術,主要目的是為了提高運行速度,和多任務。
××××××××××××××××××××××××××××××××××××需要儲備的資料(他人的)××××××××××××××××××××××××××××
××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"和
public: CUIThreadDlg m_dlg;
並在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);