C++ 關於MFC多線程編程的注意事項_C 語言

來源:互聯網
上載者:User

在多線程編程中,最簡單的方法,無非就是利用 AfxBeginThread  來建立一個背景工作執行緒,看一下這個函數的說明:

複製代碼 代碼如下:

CWinThread* AFXAPI AfxBeginThread(
AFX_THREADPROC pfnThreadProc,
LPVOID pParam,
int nPriority = THREAD_PRIORITY_NORMAL,
UINT nStackSize = 0,
DWORD dwCreateFlags = 0,
LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
);

在這個說明中,除第1和第2兩個參數外,餘下的參數都有預設值。所以,我們在使用的時候,是必須要指定前兩個參數的。

其中 第一個參數是 要啟動並執行函數的名稱,光寫函數名就可以了,不能加引號。

第二個參數,是指定 運行函數的 參數,這個參數的類型為 LPVOID 。所以要啟動並執行函數的在傳遞過去後,要轉化為LPVOID類型才可以。

而要啟動並執行參數還有一個限制,那就是必須返回一個UINT類型的結果。所以要啟動並執行函數的就有一個基本上固定的格式。

UINT RunProce(LPVOID lpParam)

在這裡還需要特別說明一下,這個函數不能是執行個體函數,也就是函數前面是不能有 類限定符:: 的。如果是靜態函數也是可以的。

在這個函數中,我們只能使用一個參數,而參數的類型只能是 LPVOID ,可以用一個結構體來封閉多個參數。

餘下的問題,就不是很多了。

關於 多線程,就寫到這裡吧!

在多線程編程中,一個很重要的問題就是,要將線程的運行過程通知介面線程,做一些顯示方面的更新。如下載線程,在適當的時候,可以更新介面,現在下載到什麼進度了。等等的情況。但是在背景工作執行緒中,是不是直接操作介面線程的控制項的。那怎麼辦呢,只能通過自訂一個訊息來解決。

工作流程,就是 在自訂線程中 通過發送一個介面上的 訊息,來通知介面做一些更新操作。在這個自訂訊息中,有一個細節要解決,那就是自訂訊息,必須要指定接收訊息的控制項控制代碼。當然你中以使用m_pApp 直接通知主架構來解決,但是這樣解決似乎繞了一個很大的圈。其實解決的方法很簡單,那就是直接將接收訊息的控制項的控制代碼傳給自訂線程,就可以了。我們直接線上程中使用此控制代碼就可以解決了。

我們知道控制項的基類都是 CWnd。所以我們傳遞一個CWnd的指標進去。當然還有一些其它的參數要一塊傳遞進去,那就做一個結構吧

複製代碼 代碼如下:

typedef struct{
 CString srcString;
 CString DesString;
 CWnd*    hander;
}Param;

這裡我們傳遞了三個參數 兩個字串一個指標。

我們先造一個自訂線程函數

複製代碼 代碼如下:

UINT RunProce(LPVOID lpParam)
{
    Param* par;
    CWnd* hander;
    par = (Param*)lpParam;
    hander = par->hander;
    myCopyDirectory(lpParam);
    CString str;
    str = "複製完成";
    hander->SendMessage(WM_USERMESSAGE,0,(LPARAM)&str);
    return 0;
}

在這個函數中,我們要運行由此函數組成的一個線程的話,就需要傳遞一個參數lpParam,而這個參數是由 Param 的結構體來指定。實際上是傳遞了三個參數進去。

複製代碼 代碼如下:

Param* par;
par = (Param*)lpParam;

我們會用上在的強制類型轉換的方法,就可以還原參數的值。根據這三個參數就  自定主的線程函數就可以運行了。那如何通知介面線程呢。看一下自訂函數裡面的這一句

hander->SendMessage(WM_USERMESSAGE,0,(LPARAM)&str);

 這一句中 hander 是由結構體轉換而來的 接收訊息的控制項的控制代碼。然後調用這個控制項的 SendMessage 方法,就可以向此控制項發訊息了。訊息的內容由後面的參數來決定

第一個參數 WM_USERMESSAGE 這是一個訊息的名稱。這個名稱實際上是一個數字。我們需要在 .h 檔案中 指定一下如下面的格式

#define WM_USERMESSAGE 11130

後面的數字造的大一點,哈哈

第二個與第三個參數,就是這個訊息傳遞具體的值,如果不需要傳遞值的話,那就直接寫0吧

在這裡我們想在傳遞參數的第三個參數上傳遞一個 字串,那就是上面的寫法了。

這樣的話,線上程中發送訊息的部分,就全部講完了。訊息發送出去了,怎麼接收呢?

這真是一個重要的問題

首先,要將訊息做一下映射。訊息映射的目的,就是告訴程式,當出現這個訊息的時候,使用哪個函數進行處理。這樣的話,就首先需要一個訊息映射的函數。這個訊息映射的函數不是亂寫,因為要傳遞兩個參數,所以這個函數需要能夠接收這兩個參數。處理函數一般這樣子寫

LRESULT CCopyfileDlg::OnProcName(WPARAM wParam, LPARAM lParam)
他奶奶的,太神奇了。傳回值只能是 LRESULT 。這個不用討論吧,照著抄吧。函數名稱後面有參數兩個,這是一個執行個體函數。因為前面有::
兩個參數一般也寫成這個樣子的。

函數內容,就由你的程式的功能決定了。我這裡直接抄一段我自己的代碼吧

LRESULT CCopyfileDlg::OnProcName(WPARAM wParam, LPARAM lParam){  // TODO: 處理使用者自訂訊息  CString* str = (CString*)lParam;  SetDlgItemText(IDC_STATIC,*str);  if(*str == "複製完成")   {     (CButton*)GetDlgItem(IDC_COPYBUT)->EnableWindow(true);   }  return 0;}

這段程式是根據得到的傳遞過來的參數,在介面上顯示具體的參數內容。

SetDlgItemText(IDC_STATIC,*str);  //在靜態文字框中顯示訊息。

備忘:

如果要讓按鈕變成灰色的,那就使用控制項的 EnableWindow 方法。

這個方法,我們說,是專門的訊息處理函數,那麼它的聲明也比較特殊。需要這麼寫

afx_msg LRESULT OnProcName(WPARAM wParam, LPARAM lParam);
將上面的內容放在 h檔案的合理位置就可以了。

現在訊息處理函數也有了。但是怎麼將映射呢?

其實在 CPP檔案中,有一個由 BEGIN_MESSAGE_MAP(CCopyfileDlg, CDialog) 和END_MESSAGE_MAP() 包括的地區。這個地區就是用來定義訊息映射的。

將這麼一句話放在他們中間,就OK了

ON_MESSAGE(WM_USERMESSAGE,OnProcName)
這麼一句話,就將 WM_USERMESSAGE 與 OnProcName 與訊息處理函數結合在一起了。是不是超級簡單呀!

這樣我們的介面線程中的訊息處理部分也主做好了。

當訊息發送過來後,就會通過訊息映射放在對應的函數中加以處理。

以上所述就是本文的全部內容了,希望大家能夠喜歡。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.