win32多线程-重写消息循环

时间:2023-03-09 09:51:03
win32多线程-重写消息循环

最近正在学习《win32多线程程序设计》,这是其中一段重写消息循环的代码事例,以后可能用的上。

  while (!quit || gNumPrinting > 0)
{ // Wait for next message or object being signaled
DWORD dwWake;
dwWake = MsgWaitForMultipleObjects(
gNumPrinting,
gPrintJobs,
FALSE,
INFINITE,
QS_ALLEVENTS); if (dwWake >= WAIT_OBJECT_0 && dwWake < WAIT_OBJECT_0 + gNumPrinting)
{ // Object has been signaled
// Reorder the handle array so we do not leave
// empty slots. Take the handle at the end of
// the array and move it into the now-empty slot.
int index = dwWake - WAIT_OBJECT_0;
gPrintJobs[index] = gPrintJobs[gNumPrinting-1];
gPrintJobs[gNumPrinting-1] = 0;
gNumPrinting--;
SendMessage(hDlgMain, WM_THREADCOUNT, gNumPrinting, 0L);
} // end if
else if (dwWake == WAIT_OBJECT_0 + gNumPrinting)
{
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{ // Get Next message in queue
if(hDlgMain == NULL || !IsDialogMessage(hDlgMain,&msg))
{
if (msg.message == WM_QUIT)
{
quit = TRUE;
exitCode = msg.wParam;
break;
} // end if
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} // end while
}
} // end while

说明:

MsgWaitForMultipleObjects函数

该函数的特点是它不但可以等待内核对象,还可以等消息。也就是当有消息到来时,该函数也一样可以返回,并处理消息,这样就给了工作线程退出的机会。

DWORD MsgWaitForMultipleObjects(

DWORD nCount, //要等待的内核对象数目

LPHANDLE pHandles, //要等待的内核对象句柄数组指针

BOOL fWaitAll, //是等待全部对象还是单个对象

DWORD dwMilliseconds,//等待时间 

DWORD dwWakeMask );//等待的消息类型

下面就详解一下该函数的参数使用方法:

DWORD nCount:要等待的内核对象的数目。如果等待两个线程退出,则nCount=2;

LPHANDLE pHandles:要等待的内核对象句柄数组指针。

如果只要等待一个线程退出,则直接设置该线程句柄的指针即可:

MsgWaitForMultipleObjects(1,&m_pThread->m_hThread,…)

如果要等待两个线程退出,则使用方法为:

HANDLE hArray[2]={ m_pThread1->m_hThread , m_pThread2->m_hThread };

MsgWaitForMultipleObjects(2,hArray,…)

BOOL fWaitAll: TRUE-表示只有要等待的线程全部退出后,此函数才返回,

               FALSE-表示要等待的线程中任意一个退出了,或是有消息到达了,此函数均会返回。

在上面的OnButton2()函数中,我要等待一个线程退出,将fWaitAll设置为

FALSE,目的是无论是线程真的退出了,还是有消息到达了,该函数都能返回。

如果将该fWaitAll设置为TRUE,那么函数返回的唯一条件是线程退出了,即便

是有消息到来了,该函数也一样不会返回。

DWORD dwMilliseconds:等待的事件,单位是毫秒。可以设置为INFINITE,无

穷等待

DWORD dwWakeMask:等待的消息类型,通常可以设置为QS_ALLINPUT。此宏表示的是可以等待任意类型的消息。当然,也可以指定等待的消息类型。

#define QS_ALLINPUT        (QS_INPUT         | \

                            QS_POSTMESSAGE   | \

                            QS_TIMER         | \

                            QS_PAINT         | \

                            QS_HOTKEY        | \

                            QS_SENDMESSAGE)

返回值:DWORD dRet 通过函数返回值,可以得到一些有效信息。函数返回值依fWaitAll设置的不同而有所不同。下面是函数返回值的几种常见类型:

dRet = 0xFFFFFFFF :   表示函数调用失败,可用GetLastError()得到具体的出错信息;

dRet =WAIT_OBJECT_0+nCount:表示有消息到达了;

如果fWaitAll设置为TRUE

dRet = WAIT_OBJECT_0,表示所有等待的核心对象都激发了,或是线程都退出了;

如果fWaitAll设置为FALSE

dRet = WAIT_OBJECT_0 ~ WAIT_OBJECT_0+nCount-1:表示等待的内核对象被激发了,index=dRet - WAIT_OBJECT_0,表示hArray[]数组中索引为index的那个对象被激发了。