title: PostMessage with WM_USER doesn't seem to arrive when MsgWaitForMultipleObjectsEx is used to check for it
body: <p>I have a program with a few thread loops that you can post tasks to. One of these thread loops is the UI thread loop. It has to handle window messages as well as the posted tasks, so I send WM_USER messages to wake the thread in the dispatch loop.</p>
  
  <p>The problem is that sometimes (specifically when there's lot of other window messages like <code>WM_PAINT</code> or <code>WM_RESIZE</code>) my <code>WM_USER</code> message doesn't wake the thread. It seems that the <code>PostMessage</code> function doesn't wake the thread from the <code>MsgWaitForMultipleObjectsEx</code> call, though I can't figure out why. </p>
  
  <p>This is what it looks like (some paraphrasing for simplicity):</p>
  
  <pre class="lang-cpp prettyprint-override"><code>#define HaveWorkMessage (WM_USER + 100)
  
  class ThreadLoopUI {
  public:
      ThreadLoopUI()
          : myHaveWork(0) {}
  
      void PostTask(Task&amp; aTask) {
          {
              ScopedLock lock(myMutex);
              myTaskQueue.push_back(aTask);
          }
  
          ScheduleWork();
      }
  
      void ScheduleWork() {
          if (InterlockedExchange(&amp;myHaveWork, 1)) {
              // No need to spam the message queue
              return;
          }
  
          if (!PostMessage(myHWnd, HaveWorkMessage, reinterpret_cast&lt;WPARAM&gt;(this), 0)) {
              std::cerr &lt;&lt; "Oh noes! Could not post!" &lt;&lt; std::endl;
          }
      }
  
      void Run() {
          for (;;) {
               // SIMPLIFICATION, SEE EDIT BELOW
               DWORD waitResult = MsgWaitForMultipleObjectsEx(0, NULL, (DWORD)INFINITE, QS_ALLINPUT, MWMO_INPUTAVAILABLE);
  
               if (waitResult == WAIT_FAILED) {
                    std::cerr &lt;&lt; "Well, that was unexpected..." &lt;&lt; std::endl;
                    continue;
               }
  
               bool doWork = false;
  
               MSG message;
               if (PeekMessage(&amp;message, NULL, 0, 0, PM_REMOVE)) {
  
                     if (message == HaveWorkMessage) {
                          doWork = true;
                          InterlockedExchange(&amp;myHaveWork, 0);
                     }
  
                     // Send the message on to the window procedure
                     TranslateMessage(&amp;message);
                     DispatchMessage(&amp;message);
               }
  
               if (doWork) {
                   // Process all tasks in work queue
               }
          }
      }
  private:
      HWND                 myHwnd;
      Mutex               myMutex;
      std::vector&lt;Task&gt;   myTaskQueue;
      LONG volatile       myHaveWork;
  }
  </code></pre>
  
  <p><strong>Edit</strong>: The direct call to <code>MsgWaitForMultipleObjectsEx</code> above was a simplification. I actually call a function that looks like this:</p>
  
  <pre class="lang-cpp prettyprint-override"><code>void WaitForMessages() {
      DWORD waitResult = MsgWaitForMultipleObjectsEx(0, NULL, (DWORD)INFINITE, QS_ALLINPUT, MWMO_INPUTAVAILABLE);
  
      if (waitResult == WAIT_OBJECT_O) {
          // Comment from the Chromium source:
          // A WM_* message is available.
          // If a parent child relationship exists between windows across threads
          // then their thread inputs are implicitly attached.
          // This causes the MsgWaitForMultipleObjectsEx API to return indicating
          // that messages are ready for processing (Specifically, mouse messages
          // intended for the child window may appear if the child window has
          // capture).
          // The subsequent PeekMessages call may fail to return any messages thus
          // causing us to enter a tight loop at times.
          // The WaitMessage call below is a workaround to give the child window
          // some time to process its input messages.
          MSG message = {0};
          DWORD queueStatus = GetQueueStatus(QS_MOUSE);
          if (HIWORD(queueStatus) &amp; QS_MOUSE &amp;&amp;
              !PeekMessage(&amp;message, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE)) 
          {
              WaitMessage();
          }               
      }
  }
  </code></pre>