When can a thread receive window messages?

Date:June 8, 2004 / year-entry #225
Tags:code
Orig Link:https://blogs.msdn.microsoft.com/oldnewthing/20040608-00/?p=38983
Comments:    16
Summary:Everybody who has messed with window messaging knows that GetMessage and PeekMessage retrieve queued messages, which are dispatched to windows via DispatchMessage. Most people also know that GetMessage and PeekMessage will also dispatch nonqueued messages. (All pending nonqueued messages are dispatched, then the first queued message is returned.) But apparently not many people realize that...

Everybody who has messed with window messaging knows that GetMessage and PeekMessage retrieve queued messages, which are dispatched to windows via DispatchMessage.

Most people also know that GetMessage and PeekMessage will also dispatch nonqueued messages. (All pending nonqueued messages are dispatched, then the first queued message is returned.)

But apparently not many people realize that SendMessage will also dispatch messages!

If one thread T1 send a message to a window that belongs to another thread T2, the sending thread T1 is put to sleep until the receiving thread replies to the message. But if somebody else sends a message to thread T1, thread T1 is woken to process the message, then is returned to sleep.

Why is that?

Well, when two threads T1 and T2 are working together, it's common that thread T1 may send a message to thread T2, and while handling the message, thread T2 will send messages back to thread T1 before it returns to T1. Therefore, thread T1 must be ready to accept incoming sent messages.

For example, thread T1 may send a message saying, "Tell me about all the X's that you know." Thread T2 will then send one message back to thread T1 saying, "Here's an X", and then another message to say "Here's another X", and so on, until it has finished telling thread T1 about all the X's, at which point it returns.

Thread T1 now knows, when the original message returns, that it has received the entire list of X's from thread 2.

This back-and-forth is how DDE service discovery works.

Another case is that thread T1 sends a message to thread T2, and thread T2 needs to ask thread T1 for help before it can finish the operation. This isn't as strange as it sounds. You do something similar all the time without realizing it when you respond to a WM_NOTIFY message by sending messages back to the control that sent the notification. (For example, you may respond to a LVN_ITEMACTIVATE by sending back a LVM_GETITEM to get information about the item that was activated.)

So remember: Any time you send a message, there is a potential for re-entrancy.


Comments (16)
  1. Jack Mathews says:

    Here’s a dumb question I just thought about. What happens when you thread 1 sends a message to thread 2, and thread 2, in the handler, decides to terminate itself? Or same with sending a process that terminates itself?

    What’s the return value of SendMessage to the caller?

  2. Doug says:

    Just one of the reasons why GUI code and multi-threaded applications is hard.

    It is amusing when you break in the debugger and see your code in the call stack 3 or 4 times, with Win32 code interspersed between them. Can make for some real entertaining bugs…

  3. Doug says:

    This is also one of the reasons why MsgWaitForMultipleObjects() is not particularly useful. You really cannot control what happens on your thread. Dialogs are one of the places that you can’t get into the Message Queue processing.

    Is there a way to get control of the Sleep that SendMessage puts the thread into? At least then you could process other events while you are waiting on the other thread….

  4. asdf says:

    LRESULT BlockingSendMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)

    {

    LRESULT ret;

    SendMessageTimeout(hwnd, msg, wp, lp, SMTO_BLOCK, INFINITE, &ret);

    return ret;

    }

    Doug: you can poll SendMessageTimeout in a PeekMessage style message loop to do what you want.

  5. Doug:

    1. MsgWaitForMultipleObjects isn’t really for GUI programming. It’s great if you have worker threads that you want to drive using a message pump though.

    2. Controlling the Sleep? Sure! You have three options that I can think of:

    a. Use PostMessage instead of SendMessage, then you won’t sleep at all.

    b. Use SendMessageTimeout so that you can expire if you’re waiting too long.

    c. Use SendReply from the thread you’re responding to the SendMessage call in, so you can wake up your other thread as soon as possible, and still continue running if you need to.

  6. Seth McCarus says:

    Simon, do you mean ReplyMessage in item c?

  7. Seth: Yep, thanks for catching that one. :) That’s what I get for replying before I get my latte :)

  8. Centaur says:

    a. Use PostMessage instead of SendMessage, then

    > you won’t sleep at all.

    But then, if you want your message answered, you have to invent another way to get your reply than the message return value, for example, by having the other thread post the reply to you.

  9. Centaur:

    Sure, but if you don’t want to sleep at all, that means that you want to be completely asynchronous anyway. So you’d need something like that.

  10. Raymond Chen says:

    SendMessageCallback.

  11. Raymond,

    Is this similar to the reason why, when you call MessageBox(), the program continues to run (i.e. other messages, such as WM_PAINT and WM_TIMER, are handled while the user is still reading the dialog box)?

    When I first starting Windows programming, this caught me off guard – since, even though I knew Windows was a multitasking / multithreading environment, my sample application only had one thread, and the code that appears immediately after the call to MessageBox() is not run until it returns – yet other parts of my program were running. Then, they were causing this same code to be run, calling MessageBox() multiple times, displaying hundreds of dialogs, until the application finally crashed.

  12. Raymond Chen says:

    No that is another issue entirely – the modal message loop. Clearly messages are dispatched while the dialog box is up – you rely on it every time you yourself call DialogBox!

    (Tearing apart dialog boxes is a month-long subject that I hope to cover in little pieces. It took me three months just to write the first week’s worth!)

  13. Raymond Chen says:

    Commenting on this entry has been closed.

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