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函式,
這個函式屬於CRT(c 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