线程间的消息通信主要采用PostThreadMessage函数来实现,主线程通过该函数来实现消息的发送,副线程则采用消息循环机制来驱动程序,当副线程无GUI时,就不能调用TranslateMessage,DispatchMessage之类的函数,因为该函数无法将消息派发至对应的窗口,这样的话,对于副线程中的MessageBox等有关窗口的消息就不能捕获,转而必须通过线程级别的钩子来实现消息处理。另外,在处理消息时,注意副线程由于无GUI导致消息队列的初始化可能会推迟,而需要调用PeekMessage函数来强制消息队列的创建,同时来通知主线程消息队列已创建完成。具体实现代码如下:
#include "stdafx.h"
#define TM_CONSUMER WM_APP + 0x100
#define TM_PRODUCER WM_APP + 0x101
#ifndef PTHREAD_START
typedef unsigned (__stdcall *PTHREAD_START) (void *);
#endif
#ifndef chBEGINTHREADEX
#define chBEGINTHREADEX(psa,cbStackSize,pfnStartAddr,\
pvParam, fdwCreate,pdwThreadID) \
((HANDLE) _beginthreadex( \
(void *)psa, \
(unsigned)(cbStackSize), \
(PTHREAD_START) (pfnStartAddr), \
(void *)(pvParam), \
(unsigned)(fdwCreate), \
(unsigned *)(pdwThreadID)))
#endif
DWORD WINAPI ThreadRun(PVOID pvParam)
{
MSG msg;
BOOL bRet;
HANDLE hEvent = (HANDLE)pvParam;
PeekMessage(&msg,NULL,WM_USER,WM_USER,PM_REMOVE);
SetEvent(hEvent);
while((bRet = GetMessage(&msg,NULL,0,0)) != 0) {
if(bRet == -1) {
printf("Fail to GetMessage:%d\n",GetLastError());
break;
} else {
switch(msg.message) {
case TM_CONSUMER:
printf("get consumer message.\n");
break;
case TM_PRODUCER:
printf("get producer message.\n");
break;
default:
break;
}
}
}
_endthreadex(0);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
// register message
DWORD workerID;
HANDLE hChild,hEvent;
BOOL bRet;
// Create an event to prevent post Message Queue
hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
// Create new thread
if(0 == (hChild = chBEGINTHREADEX(NULL,0,ThreadRun,hEvent,0,&workerID))) {
_tprintf(TEXT("fail to create thread.\n"));
return -1;
}
WaitForSingleObject(hEvent,INFINITE);
// Send Message to this newly created thread
for(int i = 0; i < 5; i++) {
if(!(bRet = PostThreadMessage(workerID,TM_CONSUMER,0,0))) {
printf("PostThreadMessage TM_CONSUMER error:%d\n",GetLastError());
}
if(!(bRet = PostThreadMessage(workerID,TM_PRODUCER,0,0))) {
printf("PostThreadMessage TM_PRODUCER error:%d\n",GetLastError());
}
}
PostThreadMessage(workerID,WM_QUIT,0,0);
//wait it quit
WaitForSingleObject(hChild,INFINITE);
CloseHandle(hChild);
getchar();
return 0;
}