windows下的多线程分为两个分支即GUI Thread和Worker Thread其实GUI在严格的意义上说是多线程的一种特例骨子里还流着单线程的血。微软提供了 AfxBeginThread创建两种线程。使用AfxBeginThread创建GUI Thread时候windows给此线程创建了一个隐含的窗口,既然是窗口消息循环机制当然不能少。窗口不停的从消息队列中取出消息,并对消息进行处理。我们可以通过消息的发送实现线程之间的通讯。当AfxBeginThread创建Worker Thread的时候就不存在什么隐含的窗口和消息机制。线程间的通信也只能通过AfxBeginThread中传递的函数来实现。有意思的是不论要传递的参数是存放在栈中还是堆中AfxBeginThread都能把参数传给之前用户指定的线程函数中。但是作为多线程编程的发烧友我就像让Worker Thread中存在消息传递机制以便让线程之间的通讯更丰富些。
下面我们就来一起探讨如何实现这个问题。既然是消息就应该定义消息ID这样worker thread才能辨别出哪个消息是做什么的。和在GUI Thread自定义消息不同在worker thread在中应以如下方法自定义消息:#define MY_APP_MESSAGE WM_APP+1;现在消息ID有了还有两个问题是如何在主线程发送(不要被主线程迷惑其实你可以在任何子线程中向另一个线程发送消息)以及如何在worker thread中接收。发送么当然要用PostThreadMessag不过首先要得到worker thread线程的ID这当然没问题,我们创造了它当然对它的一切了如指掌。在worker thread接受消息的函数是经典的GetMessage();好了万事具备了。
#define MY_APP_MESSAGE WM_APP+0X0001
HANDLE g_hEvent=NULL;
DWORD WINAPI WorkerThread(LPVOID pParam);
/////////////////////////////////////////////////////////////////////////////////
void CWokerThreadInMessageDlg::CreateWorkerThread()
{
g_hEvent=CreateEvent(NULL,
TRUE,
FALSE,
NULL);
ASSERT(g_hEvent);
m_hWorkerThread=CreateThread(NULL,
0,
WorkerThread,
this,
NULL,
&m_dwWorkerThread);
ASSERT(m_hWorkerThread);
WaitForSingleObject(g_hEvent,INFINITE);
PostThreadMessage(m_dwWorkerThread,MY_APP_MESSAGE,0,0);
}
DWORD WINAPI WorkerThread(LPVOID pParam)
{
bool bQuit=false;
MSG msg;
PeekMessage(&msg,NULL,0,0,PM_NOREMOVE);//建立消息队列参数细节见msdn
SetEvent(g_hEvent);
while(!bQuit && GetMessage(&msg,NULL,0,0))
{
switch(msg.message)
{
case MY_APP_MESSAGE:
//do the job you wanna
break;
case WM_QUIT:
bQuit=true;
break;
default:
DispatchMessage(&msg);
}
}
return 0;
}