WaitForMultipleObject与MsgWaitForMultipleObjects的用法

原文链接:http://blog.sina.com.cn/s/blog_827ed2e00100vqwv.html

一、WaitForSingleObject

函数功能: 等待一个内核对象变为已通知状态

可以使用WaitForSingleObject函数来等待一个内核对象变为已通知状态:

DWORD WaitForSingleObject(

HANDLE hObject,              //指明一个内核对象的句柄

DWORD dwMilliseconds);       //等待时间

该函数需要传递一个内核对象句柄,该句柄标识一个内核对象,如果该内核对象处于未通知状态,则该函数导致线程进入阻塞状态;如果该内核对象处于已通知状态,则该函数立即返回WAIT_OBJECT_0。第二个参数是函数的等待的时间,传递INFINITE指明要无限期等待,如果第为0,那么函数就测试同步对象的状态并立即返回。如果等待超时,该函数返回WAIT_TIMEOUT。如果该函数失败,返回WAIT_FAILED。可以通过下面的代码来判断:

 

DWORD dwResult = WaitForSingleObject(hProcess, 1000); //等待一个进程结束

switch (dwResult)

{

case WAIT_OBJECT_0:

// hProcess所代表的进程在5秒内结束

break;

 

case WAIT_TIMEOUT:

// 等待时间超过5秒

break;

 

case WAIT_FAILED:

// 函数调用失败,比如传递了一个无效的句柄

break;

}

 

二、WaitForMulitpleObjects

该函数来等待多个内核对象变为已通知状态:

    DWORD WaitForMultipleObjects(

    DWORD dwCount,                    //等待的内核对象个数

    CONST HANDLE* phObjects,          //一个存放被等待的内核对象句柄的数组

    BOOL bWaitAll,                    //是否等到所有内核对象为已通知状态后才返回

    DWORD dwMilliseconds);           //等待时间

    该函数的第一个参数指明等待的内核对象的个数,可以是0到MAXIMUM_WAIT_OBJECTS(64)中的一个值。phObjects参数是一个存放等待的内核对象句柄的数组。bWaitAll参数如果为TRUE,则只有当等待的所  有内核对象为已通知状态时函数才返回,如果为FALSE,则只要一个内核对象为已通知状态,则该函数返回。第四个参数和WaitForSingleObject中的dwMilliseconds参数类似。

    返回值:

      WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount - 1)时:如果bWaitAll为TRUE,返回值指示等待的对象被触发了,如果bWaitAll为FALSE,返回值减去WAIT_OBJECT_0指示对象数组的索引,也就是哪一个对象被触发了。

     

      WAIT_ABANDONED_0 to (WAIT_ABANDONED_0 + nCount - 1)时:如果bWaitAll为FALS,返回值指示等待的对象被触发了,并且至少有一个abandoned互斥对象,如果bWaitAll为FALSE,返回值减去WAIT_ABANDONED_0指示abandoned互斥对象的索引。

     WAIT_TIMEOUT:表示超时了,并且bWaitAll明确的所有条件都不满足。

     WAIT_FAILED:函数调用失败。

 

三、MsgWaitForMultipleObjects

函数功能:阻塞时仍可以响应消息

MsgWaitForMultipleObjects()函数类似WaitForMultipleObjects(),但它会在“对象被激发”或“消息到达队列”时被唤醒而返回。MsgWaitForMultipleObjects()多接收一个参数,允许指定哪些消息是观察对象。

 

DWORD MsgWaitForMultipleObjects(

DWORD nCount,           // 表示pHandles数组的元素个数,最大容量是MAXIMUM_WAIT_OBJECTS

LPHANDLE pHandles,      // 指向一个由对象handles组成的数组,这些handles的类型不需要相同

BOOL fWaitAll,          // 是否等待所有的handles被激发才返回

DWORD dwMilliseconds,   // 超时时间

DWORD dwWakeMask       // 欲观察的用户输入消息类型

);

 

参数

dwWakeMask

欲观察的用户输入消息类型: Value Meaning

QS_ALLEVENTS An input, WM_TIMER, WM_PAINT, WM_HOTKEY, or posted message is in the queue.

QS_ALLINPUT Any message is in the queue.

QS_ALLPOSTMESSAGE A posted message (other than those listed here) is in the queue.

QS_HOTKEY A WM_HOTKEY message is in the queue.

QS_INPUT An input message is in the queue.

QS_KEY A WM_KEYUP, WM_KEYDOWN, WM_SYSKEYUP, or WM_SYSKEYDOWN message is in the queue.

QS_MOUSE A WM_MOUSEMOVE message or mouse-button message (WM_LBUTTONUP, WM_RBUTTONDOWN, and so on).

QS_MOUSEBUTTON A mouse-button message (WM_LBUTTONUP, WM_RBUTTONDOWN, and so on).

QS_MOUSEMOVE A WM_MOUSEMOVE message is in the queue.

QS_PAINT A WM_PAINT message is in the queue.

QS_POSTMESSAGE A posted message (other than those just listed) is in the queue.

QS_SENDMESSAGE A message sent by another thread or application is in the queue.

QS_TIMER A WM_TIMER message is in the queue

 

返回值

WAIT_TIMEOUT :因时间终了而返回

WAIT_OBJECT_0 :当bWaitAll是TRUE

WAIT_OBJECT_0 to (WAIT_OBJECT_0 + nCount – 1) :bWaitAll是FALSE,将返回值减去WAIT_OBJECT_0,就表示数组中哪一个handle被激发了

WAIT_ABANDONED_0 to (WAIT_ABANDONED_0 + nCount – 1) :等待的对象中有任何mutexes

WAIT_FAILED :函数失败时返回该值

WAIT_OBJECT_0 + nCount :消息到达队列

 

MsgWaitForMultipleObjects()的正确使用方式是改写主消息循环,使得激发状态的handles得以像消息一样被对待。通常程序中只会有一个地方调用MsgWaitForMultipleObjects(),而这个调用存在于消息循环中。

注意:

1. 在收到WM_QUIT之后,Windows仍然会传送消息给你,如果要在收到WM_QUIT之后等待所有线程结束,必须继续处理你的消息,否则窗口会变得反应迟钝,而且没有重绘能力。

2.MsgWaitForMultipleObjects()不允许handles数组中有缝隙产生。所以当某个handle被激发了时,应该在下一次调用MsgWaitForMultipleObjects之前先把handles数组做个整理、紧压,不要只是把数组中的handle设为NULL

3.如果有另一个线程改变了对象数组,而那是你正在等待的,那么需要一种方法,可以强迫MsgWaitForMultipleObjects返回,并重新开始,以包含新的handle

可以向下面这样使用:

//  移除读到的所有的消息,防止界面锁住
  while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  {
   if(msg.message == WM_QUIT)
    return;
   DispatchMessage(&msg);
  }
  // 等待任何队列消息或者hThread线程句柄被触发
  result = MsgWaitForMultipleObjects(1, &hThread, FALSE, INFINITE, QS_ALLINPUT);
  if(result == WAIT_OBJECT_0)
  {
   break;
  }
  else
  {
   continue;
  }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值