程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 更多關於編程 >> C++ 關於MFC多線程編程的注意事項

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

編輯:更多關於編程

       這篇文章主要介紹了C++ 關於MFC多線程編程的注意事項的相關資料,需要的朋友可以參考下

      在多線程編程中,最簡單的方法,無非就是利用 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 。這個不用討論吧,照著抄吧。函數名稱後面有參數兩個,這是一個實例函數。因為前面有::

      兩個參數一般也寫成這個樣子的。

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

      ?

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 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 與消息處理函數結合在一起了。是不是超級簡單呀!

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

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

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

    1. 上一頁:
    2. 下一頁:
    Copyright © 程式師世界 All Rights Reserved