{"id":112218,"date":"2026-04-08T07:00:00","date_gmt":"2026-04-08T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=112218"},"modified":"2026-04-08T12:56:35","modified_gmt":"2026-04-08T19:56:35","slug":"20260408-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20260408-00\/?p=112218","title":{"rendered":"How do you add or remove a handle from an active <CODE>Msg&shy;Wait&shy;For&shy;Multiple&shy;Objects<\/CODE>?"},"content":{"rendered":"<p>A customer had a custom message loop that was built out of <code>Msg\u00adWait\u00adFor\u00adMultiple\u00adObjects<\/code>. 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 <code>Msg\u00adWait\u00adFor\u00adMultiple\u00adObjects<\/code>?<\/p>\n<p>You can&#8217;t.<\/p>\n<p>Even if you could, it meant that the return value of <code>Msg\u00adWait\u00adFor\u00adMultiple\u00adObjects<\/code> would not be useful. Suppose it returns to say &#8220;Handle number 2 was signaled.&#8221; You don&#8217;t know whether handle 2 was signaled before the handle list was updated, or whether it was signaled after. You don&#8217;t know whether it&#8217;s referring to the handle number 2 or the new one.<\/p>\n<p>So maybe it&#8217;s not a bad thing that you can&#8217;t change the list of handles in an active <code>Msg\u00adWait\u00adFor\u00adMultiple\u00adObjects<\/code>, since the result wouldn&#8217;t be useful. But you can ask the thread to stop waiting, update its handle list, and then go back to waiting.<\/p>\n<p>Since the thread is in a <code>Msg\u00adWait\u00adFor\u00adMultiple\u00adObjects<\/code>, it will wake if you send a message to a window that belongs to the thread. You can have a &#8220;handle management window&#8221; to receive these messages, say<\/p>\n<pre>#define WM_ADDHANDLE    (WM_USER+0) \/\/ wParam = index, lParam = handle\r\n#define WM_REMOVEHANDLE (WM_USER+1) \/\/ wParam = index\r\n<\/pre>\n<p>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.<\/p>\n<p>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 <code>lParam<\/code> 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.<\/p>\n<p>Next time, we&#8217;ll look at the case where you don&#8217;t want to block the background thread, or if the waiting thread is waiting in <code>Wait\u00adFor\u00adMultiple\u00adObjects<\/code> so the message option is not available.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You can&#8217;t, but you can arrange for the waiter to do it for you.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-112218","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>You can&#8217;t, but you can arrange for the waiter to do it for you.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/112218","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=112218"}],"version-history":[{"count":1,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/112218\/revisions"}],"predecessor-version":[{"id":112219,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/112218\/revisions\/112219"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=112218"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=112218"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=112218"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}