What happens to a sent message when SendMessageTimeout reaches its timeout?


The Send­Message­Timeout function tries to send a message, but gives up if the timeout elapses. What exactly happens when the timeout elapses?

It depends.

The first case is if the receiving thread never received the message at all. (I.e., if during the period the sender is waiting, the receiving thread never called GetMessage, PeekMessage, or a similar message-retrieval function which dispatches inbound sent messages.) In that case, if the timeout is reached, then the entire operation is canceled; the window manager cleans up everything and makes it look as if the call to SendMessageTimeout never took place. The message is removed from the list of the thread's non-queued messages, and when it finally gets around to calling GetMessage (or whatever), the message will not be delivered.

The second case is if the receiving thread received the message, and the message was delivered to the destination window procedure, but the receiving thread is just slow to process the message and either return from its window procedure or call Reply­Message. In that case, if the timeout is reached, then the sender is released from waiting, but the message is allowed to proceed to completion.

Since people seem to like tables, here's a timeline showing the two cases.

Sending thread Case 1 Case 2
SendMessageTimeout(WM_X) called ... not responding ... ... not responding ...
... not responding ... ... not responding ...
... not responding ... GetMessage() called
... not responding ... WndProc(WM_X) called
... not responding ... WndProc(WM_X) still executing
timeout elapses ... not responding ... WndProc(WM_X) still executing
SendMessageTimeout(WM_X) returns ... not responding ... WndProc(WM_X) still executing
... not responding ... WndProc(WM_X) returns
GetMessage() called
(message WM_X not received)

Notice that in case 2, the window manager has little choice but to let the window procedure continue with the message. After all, time travel has yet to be perfected, so the window manager can't go back in time and tell the younger version of itself, (Possibly with a slow-motion "Nooooooooooooo" for dramatic effect.) "No, don't give him the message; he won't finish processing it in time!"

If you are in case 2 and the message WM_X is a system-defined message that is subject to marshaling, then the data is not unmarshaled until the window procedure returns. It would be bad to free the memory out from under a window procedure. On the other hand, if the message is a custom message, then you are still on the hook for keeping the values valid until the window procedure is done.

But wait, how do I know when the window procedure is done? The Send­Message­Timeout function doesn't tell me! Yup, that's right. If you need to do cleanup after message processing is complete, you should use the Send­Message­Callback function, which calls you back when the receiving thread completes message processing. When the callback fires, that's when you do your cleanup.

Comments (13)
  1. Darth Vader says:

    Sadly that YouTube video seems to be devoid of content.  Fortunately, I have a replacement: http://www.youtube.com/watch .

  2. Rick C says:

    @Darth Vader:  Worked fine for me–it's a clip from Torchwood.

  3. nksingh says:

    @Chris S:

    One way of looking at it is that you shouldn't need a timeout or an asynch callback.  You shouldn't be sending a message to a guy you don't trust enough to actually process the message in a timely manner.

  4. Chris S says:

    @nksingh:

    By that logic the window messaging system can't ever be used when a response it required because you can never be sure that the program doesn't have any bugs that will cause it to hang.

    I actually have this problem at the moment where I have to communicate with a third-party program via window messages, and it has a tendency to hang periodically which causes me problems. I'm still trying to come up with a solution I like.

  5. Rick C says:

    @Chris S:  Can you not use your own timer?

  6. Adam Rosenfield says:

    @Chris: Right, it's no different from any other IPC or RPC mechanism.  You can't send an HTTP request to a web server and trust that it will process the request in a timely manner — you just have to hope it does, and provide a useful fallback when it doesn't.

  7. Chris S says:

    @Rick C:

    Yes, and I am. Problem is, I've got no way of knowing if the program will ever receive my message, so the shared memory I said it could use is basically tainted until the other program decides to respond, if that ever happens.

    It would be nice if I could replace the whole thing with a pipe based message queue, but this is a legacy system that I can't change, so I'm pretty much stuck.

  8. nksingh says:

    @Chris S:

    There's not much you can do about a legacy system, sadly. Given that Windows has progressed a bit since the early days, for new programs Window Messages should not be used for IPC.

    All I can say is that I hope you're communicating to that third-party program via a supported interface and not hacking an interface into that program through some window message tricks.

  9. Chris S says:

    @nksingh:

    No, this is the official interface that everyone must use. Pretty much every other program that uses the interface will hang the UI if the other program hangs. I'm trying to be a bit smarter about how I use it, but it's difficult because the window messaging system clearly wasn't designed to be used asynchronously.

  10. Ben Voigt says:

    @Chris: The window messaging system was most definitely designed to be used asynchronously.  That's what PostMessage is all about.

  11. Chris S says:

    @Ben Voigt:

    Sorry, I meant where a response is required, as is in what I'm doing. SendMessageCallback() is a bit limited, and there is no way to cancel requests.

  12. Chris S says:

    What if you need a timeout *and* and asynchronous callback though? There doesn't seem to be any way to do that as far as I can tell.

  13. 640k says:

    Couldn't you just sandbox an instance of the app and simulate the message receiving? "according to simulations, this app answers rapidly to messages".

Comments are closed.

Skip to main content