MFC子線程中更新控件內容的兩種辦法

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子線程中更新控件內容的兩種辦法

相關文章
相關標籤/搜索