Reputation: 6943
When we send a message, "if the specified window was created by the calling thread, the window procedure is called immediately as a subroutine".
But "if the specified window was created by a different thread, the system switches to that thread and calls the appropriate window procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code." (taken from MSDN documentation for SendMessage
).
Now, I don't understand how (or, more appropriately, when) the target windows procedure is called. Of course the target thread will not be preempted (the program counter is not changed). I presume that the call will happen during some wait function (like GetMessage
or PeekMessage
), it is true? That process is documented in detail somewhere?
Update: the rationale behind it is explained by the QS_SENDMESSAGE
flag of GetQueueStatus()
and MsgWaitForMultipleObjects()
:
QS_SENDMESSAGE
A message sent by another thread or application is in the queue.
This, along with additional remarks in MSDN documentation, means that a message sent by another thread is actually posted to the queue. Then, as soon as GetMessage
or PeekMessage
are called, it will be processed before any other posted message by being sent directly to the window procedure.
Upvotes: 11
Views: 14583
Reputation: 1469
I see some confusion here.
According to the MSDN docs, when you touch the message queue of the current thread with the intent of message processing (e.g. if you call PeekMessage
or GetMessage
), all pending sent (i.e. non-queued) messages from other threads are handled - passed to the WndProc
- and then the message queue is checked, so:
DispatchMessage
and are handled as soon as possible:
WndProc
PostThreadMessage
does just what it states - posts a message in a threads queue - such messages are not directed to any window and must be handled explixitlyDispatchMessage
are those created by PostMessage
or some system facility (timers, events, user input, etc.)SendNotifyMessage
, SendMessageTimeout
or SendMessageCallback
instead of plain SendMessage
between different threadsFor further reference, study the Remarks section of the MSDN PeekMessage
entry.
Upvotes: 8
Reputation: 222007
Every windows is associated with a thread. You can use GetWindowThreadProcessId
to retrieves the thread of every window. If you send a message to a windows from the other thread with respect of PostThreadMessage
the message will be placed in the thread's message queue. The thread must have a get-message loop (with GetMessage
for example) to get the messages and dispatch there to the window procedure of the window.
It you call SendMessage
instead of PostThreadMessage
you call the Windows Procedure directly without placing it in the message queue. Some nonqueued messages are sent also immediately to the destination window procedure, bypassing the system message queue and thread message queue. (see http://msdn.microsoft.com/en-us/library/ms644927(VS.85).aspx#nonqueued_messages). The main reason to use SendMessage
instead of PostThreadMessage
if you want to give some information from another windows (control) like read a text from an another control during processing of another message. You should do this only if it really needed. So if you use SendMessage
to send a message to a windows from another thread your current thread must be blocked for some time.
It can be a good idea to use PostThreadMessage
or SendMessageCallback
instead of SendMessage
if it is possible.
Upvotes: 1
Reputation: 104579
Short answer: When the target thread calls GetMessage (or PeekMessage) followed by DispatchMessage, then the SendMessage from the other thread is received and handled.
I am not certain if the received SendMessage preempts other messages in the queue or not. Either way, a SendMessage from one thread to another is like saying: "Post this message to the other thread's message queue. Return when that thread has finished processing it".
An now for an answer you didn't ask for:
In general, when I program interactions between the main UI thread and a worker thread, I try to avoid using SendMessage. If you aren't careful, you can get into a situation where both threads are deadlocked on each other. (Think of the case where the main thread is calling WaitForSingleObject to wait for the worker thread to complete, but the worker thread is blocked on SendMessage back to the UI thread).
Upvotes: 1