1、概述
每一個系統中都有線程(至少都有一個主線程),而線程最重要的做用就是並行處理,提升軟件的併發率。針對界面來講,還能提升界面的響應能力。通常的,爲了應用的穩定性,在數據處理等耗時操做會單獨在一個線程中運行,而全部與主UI線程有關的控件數據刷新應該到主UI線程中處理。也就是數據處理線程發消息,讓界面UI去更新控件。在MFC中線程分爲界面線程和工做者線程,界面實際就是一個線程畫出來的東西,這個線程維護一個「消息隊列」,「消息隊列」也是界面線程和工做者線程的最大區別,這個詞應該進到你的腦子裏,根深蒂固的!MFC中有兩類線程,分別稱之爲工做者線程和用戶界面線程。兩者的主要區別在於工做者線程沒有消息循環,而用戶界面線程有本身的消息隊列和消息循環。安全
在MFC中,通常用全局函數AfxBeginThread()來建立並初始化一個線程(工做者線程,還有一個重載形式是用於建立用戶界面線程)的運行。函數原型:併發
複製代碼
CWinThread* AfxBeginThread(
AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);
複製代碼
返回值: 成功時返回一個指向新線程的線程對象的指針,不然NULL。函數
pfnThreadProc:線程的入口函數,聲明必定要以下: UINT MyThreadFunction(LPVOID pParam),不能設置爲NULL。若是是類成員函數,必定要是靜態成員函數。this
pParam:傳遞入線程的參數,注意它的類型爲:LPVOID,因此咱們能夠傳遞一個結構體或者類對象到線程。通常傳遞this指針,以方便調用類的非靜態成員,由於線程函數是靜態函數。線程
nPriority:線程的優先級,通常設置爲0,讓它和主線程具備共同的優先級。指針
nStackSize:指定新建立的線程的棧的大小。若是爲 0,新建立的線程具備和主線程同樣的大小的棧。對象
dwCreateFlags:指定建立線程之後,線程有怎麼樣的標誌。能夠指定兩個值:CREATE_SUSPENDED:線程建立之後,會處於掛起狀態,直到調用:ResumeThread。0 : 建立線程後就開始運行。隊列
lpSecurityAttrs:指向一個 SECURITY_ATTRIBUTES 的結構體,用它來標誌新建立線程的安全性。若是爲 NULL,那麼新建立的線程就具備和主線程同樣的安全性。原型
常見用法:消息隊列
AfxBeginThread(MyThreadFunction, this);
傳遞線程參數爲this,即類自己,是爲了能在線程函數中得到類中非靜態成員變量,由於線程函數是靜態函數。
MFC子線程中更新控件內容有兩種方法,一種是在子線程中經過全局函數更新控件內容,一種是在子線程中經過發送自定義消息來更新控件內容。
2、經過全局函數更新控件內容
1.在對話框類CThreadDemoDlg中添加成員變量——線程對象的指針和線程函數
CWinThread *m_pThread;
static UINT ThreadFunction(LPVOID pParam);
2.實現線程函數,使用全局函數::SetWindowText、::GetDlgItem更新控件內容
複製代碼
UINT CThreadDemoDlg::ThreadFunction(LPVOID pParam)
{
CThreadDemoDlg *pDlg = (CThreadDemoDlg *)pParam;
while (TRUE) {
::SetWindowText(::GetDlgItem(pDlg->m_hWnd, IDC_STATIC), L"Hello World");
Sleep(1000);
::SetWindowText(::GetDlgItem(pDlg->m_hWnd, IDC_STATIC), L"Hello Android");
Sleep(1000);
}
return 0;
}
複製代碼
3.在成員函數OnInitDialog建立線程並啓動
m_pThread = AfxBeginThread((AFX_THREADPROC)ThreadFunction, this);
3、經過發送自定義消息更新控件內容
1.在頭文件中定義消息ID
#define WM_UPDATE_STATIC (WM_USER + 100)
2.在對話框類CThreadDemoDlg中添加成員——線程對象的指針和線程函數
CWinThread *m_pThread;
static UINT ThreadFunction(LPVOID pParam);
3.聲明自定義的消息函數
afx_msg LRESULT OnUpdateStatic(WPARAM wParam, LPARAM lParam);
4.在CPP文件中添加消息映射
BEGIN_MESSAGE_MAP(CThreadDemoDlg, CDialog)
//......
ON_MESSAGE(WM_UPDATE_STATIC, &CThreadDemoDlg::OnUpdateStatic)
//......
END_MESSAGE_MAP()
5.實現自定義消息響應函數
複製代碼
LRESULT CThreadDemoDlg::OnUpdateStatic(WPARAM wParam, LPARAM lParam)
{
if (wParam == 0) {
GetDlgItem(IDC_STATIC)->SetWindowText(L"Hello Linux");
} else {
GetDlgItem(IDC_STATIC)->SetWindowText(L"Hello Windows");
}
return 0;
}
複製代碼
6.實現線程函數,並經過PostMessage發送自定義消息
複製代碼
UINT CThreadDemoDlg::ThreadFunction(LPVOID pParam)
{
CThreadDemoDlg *pDlg = (CThreadDemoDlg *)pParam;
while (TRUE) {
::PostMessage(pDlg->m_hWnd, WM_UPDATE_STATIC, 0, 0);
Sleep(1000);
::PostMessage(pDlg->m_hWnd, WM_UPDATE_STATIC, 1, 0);
Sleep(1000);
}
return 0;
}
複製代碼
7.在成員函數OnInitDialog建立線程並啓動
m_pThread = AfxBeginThread((AFX_THREADPROC)ThreadFunction, this);
經過發送自定義消息更新控件內容整體思路:在主界面所在的主線程中建立線程--->將線程的起始函數綁定到類的靜態成員方法--->在靜態成員方法中調用PostMessage()或SendMessage()發送自定義消息--->在自定義消息的消息響應函數中更新主界面上控件的狀態顯示。 原文連接:MFC子線程中更新控件內容的兩種辦法