April 8th, 2026
like1 reaction

How do you add or remove a handle from an active Msg­Wait­For­Multiple­Objects?

A customer had a custom message loop that was built out of Msg­Wait­For­Multiple­Objects. Occasionally, they needed to change the list of handles that the message loop was waiting for. How do you add or remove a handle from an active Msg­Wait­For­Multiple­Objects?

You can’t.

Even if you could, it meant that the return value of Msg­Wait­For­Multiple­Objects would not be useful. Suppose it returns to say “Handle number 2 was signaled.” You don’t know whether handle 2 was signaled before the handle list was updated, or whether it was signaled after. You don’t know whether it’s referring to the handle number 2 or the new one.

So maybe it’s not a bad thing that you can’t change the list of handles in an active Msg­Wait­For­Multiple­Objects, since the result wouldn’t be useful. But you can ask the thread to stop waiting, update its handle list, and then go back to waiting.

Since the thread is in a Msg­Wait­For­Multiple­Objects, it will wake if you send a message to a window that belongs to the thread. You can have a “handle management window” to receive these messages, say

#define WM_ADDHANDLE    (WM_USER+0) // wParam = index, lParam = handle
#define WM_REMOVEHANDLE (WM_USER+1) // wParam = index

The background thread could send one of these messages if it wanted to add or remove a handle, and the message procedure would perform the corresponding operation.

In reality, you probably need more information than just the handle; you also need to know what to do if that handle is signaled. The lParam is more likely to be a pointer to a structure containing the handle as well as instructions on what the handle means. Those instructions could take the form of a callback function, or it could just be a value from an enum. Pick the design that works for you.

Next time, we’ll look at the case where you don’t want to block the background thread, or if the waiting thread is waiting in Wait­For­Multiple­Objects so the message option is not available.

Topics

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

1 comment

Sort by :
  • GL

    The simplest idea is to add a dedicated event object to the list of `WaitForMultipleObjects` that serves as a notifier of handle addition/removal. When a handle needs to be added/removed, place the handle to add/remove in a synchronized queue (in case there are many updates) and signal the event. The waiting thread wakes up, sees it's the handle add/removal event, drains the change queue, resets the event, releases the queue, then goes back to waiting.

    The above assumes bWaitAll or its equivalent is false. In case it's wait-all, addition is simple --- after waking up, wait again on any added handles....

    Read more