You can call MsgWaitForMultipleObjects with zero handles

Date:January 25, 2006 / year-entry #33
Tags:code
Orig Link:https://blogs.msdn.microsoft.com/oldnewthing/20060125-18/?p=32533
Comments:    11
Summary: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...

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.


*DISCLAIMER: I DO NOT OWN THIS CONTENT. If you are the owner and would like it removed, please contact me. The content herein is an archived reproduction of entries from Raymond Chen's "Old New Thing" Blog (most recent link is here). It may have slight formatting modifications for consistency and to improve readability.

WHY DID I DUPLICATE THIS CONTENT HERE? Let me first say this site has never had anything to sell and has never shown ads of any kind. I have nothing monetarily to gain by duplicating content here. Because I had made my own local copy of this content throughout the years, for ease of using tools like grep, I decided to put it online after I discovered some of the original content previously and publicly available, had disappeared approximately early to mid 2019. At the same time, I present the content in an easily accessible theme-agnostic way.

The information provided by Raymond's blog is, for all practical purposes, more authoritative on Windows Development than Microsoft's own MSDN documentation and should be considered supplemental reading to that documentation. The wealth of missing details provided by this blog that Microsoft could not or did not document about Windows over the years is vital enough, many would agree an online "backup" of these details is a necessary endeavor. Specifics include:

<-- Back to Old New Thing Archive Index