You can call MsgWaitForMultipleObjects with zero handles


There is no WaitMessageTimeout function, but you can create your own with the assistance of the MsgWaitForMultipleObjects function.

BOOL WaitMessageTimeout(DWORD dwTimeout)
{
 return MsgWaitForMultipleObjects(
    0, NULL, FALSE, dwTimeout, QS_ALLINPUT)
      == WAIT_TIMEOUT;
}

To wait for a message with timeout, we use the MsgWaitForMultipleObjects in a vacuous sense: You pass it a list of objects you want to wait for, as well as a timeout and a set of queue states, asking that the function return when any of the objects is signalled or when a message is ready. By passing no objects, the only thing left to wait for is an incoming message.

Next time, we'll see how this basic idea can be used to build a slightly more complex function.

[1/26: Fix call to MsgWaitForMultipleObjects; had it confused with MsgWaitForMultipleObjectsEx. That's what happens when you write entries on an airplane.]

Comments (11)
  1. Mike Dimmick says:

    Quick note (and I’m sure Raymond has mentioned this before): when MsgWaitForMultipleObjects returns WAIT_OBJECT_0 + nCount to signify that a message arrived, it means that a new message has arrived since the last time you called MsgWaitEtc. If more than one message was queued, you should process all of them, because your next call to MsgWaitForMultipleObjects will block until a further message is queued (or the timeout expires, or one of the objects is signalled).

    I normally call PeekMessage(…, PM_REMOVE) in a loop if MsgWaitEtc indicates queued messages.

  2. Matt Sayler says:

    I’m a bit unclear here, but this looks surprisingly similar to the use of select() in POSIXland.

  3. Coleman says:

    How is MsgWait different from plain old WaitForMultipleObjects? Is it because it waits for a pre-defines list of objects?

    I’ve always used the non Msg versions of these functions in the past.

    Matt, this is more akin to the pthread_condition_variable stuff in POSIX. Both POSIX and Windows have select(). select is used to wait for input from a number of file desciptors. You can also use select for high resolution timers. e.g. pausing with 5 ms resolution.

  4. Tim Lesher says:

    Nice… and I think I see where you’re going with this. ;-)

    Coleman: MsgWaitForMultipleObjects is useful when you want to wait either for an object to be signalled, or for a message to get put into the thread queue.

    In POSIX-land, select handles all of these kinds of cases, because (all together now!) in POSIX, all the world’s a file descriptor.

  5. SuperKoko says:

    > But if MsgWaitForEtc can wait for window messages too, then never mind, it isn’t "more general". Well, it may be (I’m not sure), but not for this reason.

    It does.

    Actually, you can specify a "mask" of messages to handle, which can include WM_PAINT messages, keyboard messages, SendMessage’s messages, mouse messages, etc.

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/msgwaitformultipleobjects.asp

    I wonder if there is a safe method to treat all messages before calling MsgWaitForMultipleObjects.

    Even using PeekMessage, a new message might be recieved just after the last PeekMessage has returned and just before the MsgWaitForMultipleObjects is executed.

    This is unlikely to happen, but may happen.

    Setting a dummy timer which sends dummy messages, just to make MsgWaitForMultipleObjects return at regular intervals (or using a small timeout), partially solves the problem, but introduces a conceputal flaw, and a performance reduction (like the "Performance consequences of polling" article explained).

  6. BryanK says:

    Actually, if MsgWaitForEtc only waits for thread messages, then POSIX’s select() is more general. Because in POSIX-land, the equivalent of WM_PAINT (which is a window message in Win32, not a thread message — right?) is sent to your X11 socket, which can be put into one or more of the select() FD_SETs.

    So select() can handle more than just wait objects and (X11’s version of) thread messages — it can handle wait objects plus *any* (X11) message.

    But if MsgWaitForEtc can wait for window messages too, then never mind, it isn’t "more general". Well, it may be (I’m not sure), but not for this reason.

  7. SuperKoko: I already discussed the lack-of-race-condition last year. http://blogs.msdn.com/oldnewthing/archive/2005/02/17/375307.aspx

  8. Richard says:

    "MWFMO_WAITANY"? Is this a local synonym for TRUE? I can’t find it on MSDN (VS2005 version).

  9. Stu says:

    Now that we’ve mentioned POSIX (and X11), doesn’t everyone think that using select() is sooo much easier that having to remember all those WaitFor* calls in windows?

    Besides, if I’m waiting on a socket or pipe on *nix, is just use a blocking read() or recv().

  10. I mentally swapped MsgWaitForMultipleObjects and MsgWaitForMultipleObjectsEx, sorry. But if you understand the underlying message you should have been able to fix the problem yourself. (Consider it an unintended exercise for the reader.)

  11. Anonymous Terrorist says:

    [1/26: Fix call to MsgWaitForMultipleObjects;

    > had it confused with

    > MsgWaitForMultipleObjectsEx.

    > That’s what happens when you write entries

    > on an airplane.]

    When you write entries on an airplane, Ex maniacs slip corruption into your code?

Comments are closed.