1. 程式人生 > >PostThreadMessage和SendMessage用法+結合CreateThread多執行緒講解

PostThreadMessage和SendMessage用法+結合CreateThread多執行緒講解

提示:有關函式及其引數介紹大家直接百科就行了,這裡只介紹具體用法。

一、SendMessage

首先我們來學習一下如何使用SendMessage函式,這個函式線上程中呼叫後,訊息發出到訊息接收函式,

該執行緒必須等到訊息接收函式執行完畢才能繼續向下執行。這也是它和PostThreadMessage最大的區別。

後者只需要丟擲訊息,然後繼續執行,不需等待接受訊息函式執行完。

比較完整的做法,六步就可執行完畢,希望讀者有些耐心,並且能真正理解其用法的含義。

1.

//首先要自定義一個使用者訊息,我們一般用WM_USER +n來定義訊息ID,n要大於100,小於100的已經被系統訊息ID佔用。

該操作一般位於標頭檔案中。

#define WM_USERLOGIN_RSP WM_USER+102 //賬號登入響應

2.

//宣告一個函式用於接收訊息。一般也放在標頭檔案中

afx_msg LRESULT OnUserLogin(WPARAM wParam,LPARAM lParam);

3.

//給訊息繫結接收函式

ON_MESSAGE(WM_USERLOGIN_RSP,OnUserLogin)

如果是基於MFC程式設計,在

//將訊息和函式繫結

BEGIN_MESSAGE_MAP(CTraVariety, CDialog)

//{{AFX_MSG_MAP(CTraVariety)

、、、、、、、、

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

裡面新增這句程式碼即可

4.

//定義訊息接收函式,該函式位於下面的第5步中 控制代碼所代表的區域

LRESULT CTraVariety::OnUserLogin(WPARAM wParam,LPARAM lParam)//登入成功訊息

{

CString *nameMsg = (CString *)wParam;

/*********/

}

5.該控制代碼要包含上述第4步中的訊息接收函式

//確定一個用來接收訊息的控制代碼,

比如我們可以這樣做:

HWND m_hMainWnd;//控制代碼變數

//給控制代碼賦值

void CTraVariety::CTPInitWnd(CTraderSpi* UserSpi)

{

// pUserSpi的訊息響應視窗設定為本視窗  //傳遞主視窗控制代碼:

UserSpi->SetHwnd(this->m_hWnd);

}

SetHwnd()函式定義如下:

void CTraderSpi::SetHwnd(HWND hWnd)

{

m_hMainWnd = hWnd;

}

6.最後,你就可以隨意使用SendMessage了,第一個引數是你想讓這個訊息傳送到哪個控制代碼,第二個引數是訊息的名,

第三個引數是傳送的資料

//傳送自定義訊息

::SendMessage(m_hMainWnd,WM_USERLOGIN_RSP,(WPARAM)nameMsg,NULL);

二、PostThreadMessage用法

學會了SendMessage的用法,PostThreadMessage其實是一樣的,不過SendMessage函式的第一個引數是控制代碼,

struct HWND__ *型別,但是PostThreadMessage的第一個引數是DWORD型別,用來表示執行緒ID

所以其使用一般是結合多執行緒來使用,所以我們有必要談一下CreateThread()這個函式。

CreateThread()屬於Windows Api,其實並不建議大家使用,更經常使用的是_beginThread函式,

這個函式屬於CRTc running time)函式,是編譯器帶的,但是底層同樣呼叫了CreateThread

這個我們先不討論,有關_beginThread使用方法大家可以參考我的另一篇文章——使用_beginThread建立自己的Thread基類。

(不發連結了(*^__^*) 每次發連結都被稽核,童鞋們有興趣就自己翻一翻)。

比如現在我們要建立一個日誌執行緒,專門用來儲存日誌,TradeProc()作為訊息接收入口函式,

接收其他各個執行緒傳送來的資料,並不影響其他執行緒繼續工作。

1.

//首先要宣告變數:

HANDLE  m_hTradeThread; //用來表示執行緒

DWORD m_dwTradeId; //用來記錄執行緒ID

2.

//使用CreateThread將執行緒和ID繫結到函式TradeProc上,函式名就是入口地址(不多解釋)

m_hTradeThread = CreateThread( NULL,0,TradeProc,(LPVOID)this,0,&m_dwTradeId); //日誌執行緒

if (m_hTradeThread == NULL)

{

AfxMessageBox("建立日誌記錄執行緒失敗!");

  }

3.入口函式的定義

//當然函式要提前宣告或者位置要在繫結的前方

DWORD WINAPI TradeProc(LPVOID lpParameter) //日誌執行緒函式

{

MSG msg;

while(GetMessage(&msg,NULL,0,0))

{

//做你想做的事情

//such as  :   Public.CreateRecord(LogRecord);

}

return 1;

}

其中的GetMessage()專門用來接收PostThreadMessage()發出的訊息,當沒有訊息發出時,該執行緒一直處於阻塞狀態,

一旦接收到訊息,就可以根據訊息型別或內容做你想做的事兒。我一般的做法是:建立一個主接收訊息執行緒,

給不同的訊息(資料)標識不同的型別,接收到訊息後根據訊息型別立即丟擲到相對應的子執行緒中,

不影響下一次的訊息接收,並可以效率比較高,但是可能會耗費記憶體喔。當然這些設計思想要根據實際的需求,最後還得取決於你。

4.

最後,你又可以隨意使用PostThreadMessage()了:

PostThreadMessage(m_dwTradeId,0,(WPARAM)m_tuse,1); //傳送訊息

想詳細討論的童鞋可以加Q 1466231850