windows WaitForMultipleObjects / MsgWaitForMultipleObjects 区别

windows WaitForMultipleObjects / MsgWaitForMultipleObjects difference

我正在尝试了解 MsgWaitForWaitFor 函数之间的区别。

1) 我理解 MsgWaitFor 在消息循环下是 运行,而 WaitFor 不是?
2) MsgWaitFor 函数是否更适合需要连续接收一系列事件的应用程序? Windows 是否对消息进行排队,以便应用程序不会错过任何事件? 假设应用程序想要接收经常发生的事件 AB。 该应用程序将打开一个线程:

while (1) {
  ret = WaitForMultipleObjects(...); // wait for events A and B
  if (ret == WAIT_OBJECT_0) {
    process_event();
  }
}

问题是,当线程忙于处理时,这意味着它当前没有被 WaitForMultipleObjects 阻塞。线程如何才能避免错过事件,直到它返回等待?

两个MsgWaitForMultipleObjects[Ex] and WaitForMultipleObjects[Ex] internal call the same api - KeWaitForMultipleObjects

不同之处 - MsgWaitForMultipleObjects[Ex] 将事件(在前面,在 0 索引处)添加到对象句柄数组。因为 KeWaitForMultipleObjects 将对象的最大数量限制为 MAXIMUM_WAIT_OBJECTS,同样的限制还有 WaitForMultipleObjects[Ex]MAXIMUM_WAIT_OBJECTS - 1 MsgWaitForMultipleObjects[Ex](因为使用了额外的 +1 事件对象)

exist only 2 WAIT_TYPE - WaitAll,表示所有指定的对象必须在等待满足之前达到信号状态;或 WaitAny,表示任何一个对象在等待满足之前必须达到信号状态。

当我们等待对象收到信号时 - 在我们开始等待之前或之后对象是否处于信号状态并不重要。无论如何我们不会错过信号状态。当然,如果我们手动不将对象重置为不再发出信号状态。但这已经是程序逻辑问题,与等待无关 api

sequence of events in a row

这里不存在任何序列。每个对象都可以处于两种状态(有信号或无信号),我们可以等待所有或任何处于有信号状态的对象。如果您等待任何 - 首先向哪个对象发出信号取决于具体情况。

Does Windows queues the messages, so the application won't miss any events?

根本没有任何消息。仅存在内部带有 DISPATCHER_HEADER(查看 wdm.h)的对象。等待 api 检查 DISPATCHER_HEADERSignalState,如果它已经设置 - return 控制(如果我们等待单个对象或任何对象当然)。如果不是 - 将线程插入 WaitListHead (这是双链表,可以是多个线程,等待这个对象,并从 win8 开始 - WaitCompletionPacket's 对象。当对象转到信号状态(SignalState 设置为非零)。系统首先唤醒(SynchronizationEvent)或全部(NotificationEvent,其他对象类型) WaitListHead 中的等待线程(再次基于 waitall 或 wait any)。如果 WaitCompletionPacket - 它排队到 iocp

所以再次 - 我们没有遗漏(如果不再次自行重置对象)

I'm trying to understand the difference between MsgWaitFor and WaitFor functions.

主要区别是 MsgWaitForMultipleObjects/MsgWaitForMultipleObjectsEx 除了以下对象类型外,还可以等待消息(在消息队列中):

  • 更改通知
  • 控制台输入
  • 事件
  • 内存资源通知
  • 互斥
  • 进程
  • 信号量
  • 线程
  • 可等待计时器

因此,如果您有创建 windows 的线程,请使用 MsgWaitForMultipleObjectsMsgWaitForMultipleObjectsEx,而不是 WaitForMultipleObjectsEx

The question is, when the thread is busy with processing, meaning it is currently not blocked by WaitForMultipleObjects. How can the thread avoid missing the events until it goes back to waiting?

Message 有队列并且队列有长度(10,000 posted messages). So when processing messages too slow, the PostMessage 可能因 ERROR_NOT_ENOUGH_QUOTA 而失败。但是对于接收方,你不会错过消息和您可以一条一条地处理排队的消息。

Event 对象没有队列,它有两个状态:signalednonsignaledSetting an event that is already set has no effect. So if this is a manual-reset event object, it remains signaled until it is set explicitly to the nonsignaled state by the ResetEvent 函数。设置侧可能会漏掉而不是检查侧。