1. 程式人生 > >MFC子執行緒中更新控制元件內容的兩種辦法

MFC子執行緒中更新控制元件內容的兩種辦法

一、概述


每個系統中都有執行緒(至少都有一個主執行緒),而執行緒最重要的作用就是並行處理,提高軟體的併發率。針對介面來說,還能提高介面的響應能力。一般的,為了應用的穩定性,在資料處理等耗時操作會單獨在一個執行緒中執行,而所有與主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。如果是類成員函式,一定要是靜態成員函式。

pParam:傳遞入執行緒的引數,注意它的型別為:LPVOID,所以我們可以傳遞一個結構體或者類物件到執行緒。一般傳遞this指標,以方便呼叫類的非靜態成員,因為執行緒函式是靜態函式。

nPriority:執行緒的優先順序,一般設定為0,讓它和主執行緒具有共同的優先順序。

nStackSize:指定新建立的執行緒的棧的大小。如果為 0,新建立的執行緒具有和主執行緒一樣的大小的棧。

dwCreateFlags:指定建立執行緒以後,執行緒有怎麼樣的標誌。可以指定兩個值:CREATE_SUSPENDED:執行緒建立以後,會處於掛起狀態,直到呼叫:ResumeThread。0 : 建立執行緒後就開始執行。

lpSecurityAttrs:指向一個 SECURITY_ATTRIBUTES 的結構體,用它來標誌新建立執行緒的安全性。如果為 NULL,那麼新建立的執行緒就具有和主執行緒一樣的安全性。

常見用法:

AfxBeginThread(MyThreadFunction, this);

傳遞執行緒引數為this,即類本身,是為了能線上程函式中獲得類中非靜態成員變數,因為執行緒函式是靜態函式。

MFC子執行緒中更新控制元件內容有兩種方法,一種是在子執行緒中通過全域性函式更新控制元件內容,一種是在子執行緒中通過傳送自定義訊息來更新控制元件內容。


二、通過全域性函式更新控制元件內容


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); 

三、通過傳送自定義訊息更新控制元件內容


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); 


轉載,原文連結:https://blog.csdn.net/dezhihuang/article/details/73499998