views:

234

answers:

4

How precisely does windows decide that SendMessage should return- that is, how does it decide the receiving thread has finished processing the sent message?

Detailed scenario: I've got thread A using SendMessage to send a thread to thread B. Obviously SendMessage doesn't return until thread B finishes processing the message. Thread B pops up a dialog box and starts pumping messages. In my scenario, there is a WM_KILLFOCUS message on the queue which gets pumped by thread B. This results is a WM_COMMAND message on thread B. Thread B passes this WM_COMMAND message to the default window proc. When it does this, SendMessage returns back to thread A, even though the original message hasn't finished processing yet! What is going on? It looks like somehow the default window proc is confusing windows into thinking the original sent message is finished.

So are there known scenarios where pumping messages and calling the default window proc can trick SendMessage into returning?

Thanks! Phil

+2  A: 

Since SendMessage has a return value, it is always after the message is processed.

PostMessage on the other hand will not wait for the message to be processed.

From MSDN on SendMessage:

The SendMessage function calls the window procedure for the specified window and does not return until the window procedure has processed the message.

There is no case where it will return before the message is processed.

Brian R. Bondy
A: 

It sounds as if your original SendMessage has NOT returned but rather than the WindowProc in thread A has been called during the processing of the message sent. There is no requirement that a message handler must refrain from calling SendMessage in response to receipt of a message.

You should be able to see the original call to SendMessage in your callstack at the point where you receive the WM_COMMAND that you sent in response to the focus change message.

sean e
The original call to SendMessage is definitely returning. I have a breakpoint on the line immediately following it. When I hit this breakpoint on Thread A, thread B is in the call to the DefWndProc with a WM_COMMAND message, and it is underneath the processing of the original sent message. It's definitely returning early.
I can't see the code - but in the case of a breakpoint in a WindowProc, hitting a breakpoint would not necessarily disprove re-entrancy. You would need to inspect the callstack at the time the breakpoint is hit to either confirm or rule-out re-entrancy. But take this lightly - I don't have the context/perspective and details that you have.
sean e
+1  A: 

From the MSDN, it sounds like that the problem may be that displaying a dialog box in thread B may cause deadlocks. See Message Deadlocks.


Possibly it is because the message received by thread A was a nonqueued message. From MSDN:

However, the sending thread will process incoming nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. For more information on nonqueued messages, see Nonqueued Messages.

gwell
+3  A: 

As long as processing of the message has started, the WindowProc processing the interthread message can call ReplyMessage to allow the calling thread to continue while processing continues.

Chris Becke
+1 Wow - that API has been around since Win95, but I've never come across it...
sean e