{"id":36423,"date":"2005-02-17T07:00:00","date_gmt":"2005-02-17T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2005\/02\/17\/msgwaitformultipleobjects-and-the-queue-state\/"},"modified":"2019-07-04T13:48:41","modified_gmt":"2019-07-04T20:48:41","slug":"msgwaitformultipleobjects-and-the-queue-state","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20050217-00\/?p=36423","title":{"rendered":"MsgWaitForMultipleObjects and the queue state"},"content":{"rendered":"<p>One danger of <a href=\"http:\/\/msdn.microsoft.com\/library\/en-us\/dllproc\/base\/msgwaitformultipleobjects.asp\"> the <code>MsgWaitForMultipleObjects<\/code> function<\/a> is calling it when there are already messages waiting to be processed, because <code>MsgWaitForMultipleObjects<\/code> returns only when there is a <strong>new<\/strong> event in the queue.<\/p>\n<p>In other words, consider the following scenario:<\/p>\n<ul>\n<li><code>PeekMessage(&amp;msg, NULL, 0, 0, PM_NOREMOVE)<\/code> returns <code>TRUE<\/code> indicating that there is a message.<\/li>\n<li>Instead of processing the message, you ignore it and call <code>MsgWaitForMultipleObjects<\/code>.<\/li>\n<\/ul>\n<p>This wait will <strong>not<\/strong> return immediately, even though there is a message in the queue. That&#8217;s because the call to <code>PeekMessage<\/code> told you that a message was ready, and you willfully ignored it. The <code>MsgWaitForMultipleObjects<\/code> message tells you only when there are new messages; any message that you already knew about doesn&#8217;t count.<\/p>\n<p>A common variation on this is the following:<\/p>\n<ul>\n<li><code>MsgWaitForMultipleObjects<\/code> returns that there is a message.<\/li>\n<li>You call <code>PeekMessage(&amp;msg, NULL, 0, 0, PM_REMOVE)<\/code> and process that message.<\/li>\n<li>You call <code>MsgWaitForMultipleObjects<\/code> to wait for more messages.<\/li>\n<\/ul>\n<p>If it so happens that there were <strong>two<\/strong> messages in your queue, the <code>MsgWaitForMultipleObjects<\/code> does not return immediately, because there are no new messages; there is an old message you willfully ignored, however.<\/p>\n<p>When <code>MsgWaitForMultipleObjects<\/code> tells you that there is a message in your message queue, you have to process <strong>all<\/strong> of the messages until <code>PeekMessage<\/code> returns <code>FALSE<\/code>, indicating that there are no more messages.<\/p>\n<p>Note, however, that this sequence is not a problem:<\/p>\n<ul>\n<li><code>PeekMessage(&amp;msg, NULL, 0, 0, PM_NOREMOVE)<\/code> returns <code>FALSE<\/code> indicating that there is no message.<\/li>\n<li>A message is posted into your queue.<\/li>\n<li>You call <code>MsgWaitForMultipleObjects<\/code> and include the <code>QS_ALLPOSTMESSAGE<\/code> flag.<\/li>\n<\/ul>\n<p>This wait does return immediately, because the incoming posted message sets the &#8220;There is a new message in the queue that nobody knows about&#8221; flag, which <code>QS_ALLPOSTMESSAGE<\/code> matches and therefore causes <code>MsgWaitForMultipleObjects<\/code> to return immediately.<\/p>\n<p><a href=\"http:\/\/msdn.microsoft.com\/library\/en-us\/dllproc\/base\/msgwaitformultipleobjectsex.asp\"> The <code>MsgWaitForMultipleObjectsEx<\/code> function<\/a> lets you pass the <code>MWMO_INPUTAVAILABLE<\/code> flag to indicate that it should check for previously-ignored input.<\/p>\n<p>Armed with this knowledge, explain why the observed behavior with the following code is &#8220;Sometimes my program gets stuck and reports one fewer record than it should. I have to jiggle the mouse to get the value to update. After a while longer, it falls two behind, then three&#8230;&#8221;<\/p>\n<pre>\/\/ Assume that there is a worker thread that processes records and\r\n\/\/ posts a WM_NEWRECORD message for each new record.\r\nBOOL WaitForNRecords(HANDLE h, UINT cRecordsExpected)\r\n{\r\n  MSG msg;\r\n  UINT cRecords = 0;\r\n  while (true) {\r\n    switch (MsgWaitForMultipleObjects(1, &amp;h,\r\n                         FALSE, INFINITE, QS_ALLINPUT)) {\r\n    case WAIT_OBJECT_0:\r\n      DoSomethingWith(h); \/\/ event has been signalled\r\n      break;\r\n    case WAIT_OBJECT_1:\r\n      \/\/ we have a message - peek and dispatch it\r\n      if (PeekMessage(&amp;msg, NULL, 0, 0, PM_REMOVE)) {\r\n        TranslateMessage(&amp;msg);\r\n        DispatchMessage(&amp;msg);\r\n      }\r\n      if (SendMessage(hwndNotify, WM_GETRECORDCOUNT,\r\n                      0, 0) &gt;= cRecordsExpected) {\r\n        return TRUE; \/\/ we got enough records\r\n      }\r\n      break;\r\n    default:\r\n      return FALSE; \/\/ unexpected failure\r\n    }\r\n  }\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>It waits only for messages that have arrived since the last time you checked.<\/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-36423","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>It waits only for messages that have arrived since the last time you checked.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/36423","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=36423"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/36423\/revisions"}],"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=36423"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=36423"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=36423"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}