More on Messages and Threads
Preempting or nonpreempting?
While the thread system is preemptive, the message system is not. A thread
is preempted solely to let other threads run. A thread is never preempted
to change its point of execution. Thus a thread is never preempted for
the purpose of switching message handlers.
In order to handle messages for several windows,
the execution point must switch between the various window procedures.
If the windows are in separate threads, this happens automatically, but
you might need to worry about racing conditions. If the windows
are in the same thread, then each window must give up the thread to allow
the other window procedures to run. This means that a message sent
from another thread does not invoke a window procedure until the receiving
thread is ready to receive a message. Or, to state it another way, a SendMessage
from one thread to another doesn't necessarily take effect immediately.
When is a thread ready to receive sent messages?
Guess what! When it calls GetMessage, PeekMessage, or WaitMessage. The
only exception is the same-thread message send that acts like a subroutine
call.
SendMessage and ReplyMessage
The confusing part of a message send (SendMessage call) is its modelling
as a subroutine call. A thread cannot execute an arbitrary window procedure
because its window might be in another process! Thus the window procedure
must be executed by a destination thread. Preemption for this purpose would
require building a preemption stack. Instead, Windows uses a Sender, Queue,
and Receiver setup. Windows simply buries the "send" Receiver in the "post"
Receiver routines.
When SendMessage sends a message to a window in
another thread, it waits for a reply which is issued when
the receiver calls ReplyMessage. Another way of stating this is: a SendMessage
call will block the thread, until a reply unblocks
it.
An explicit reply is usually not necessary because
when a window procedure exits, ReplyMessage is automatically called. An
explicit ReplyMessage will be necessary to avoid deadlock
if there is chain of SendMessage calls that involves more than one thread
in a circular fashion. [See Deadlock Theory.]
For example:
The SendMessage chain
window A, thread 1 --> B,
thread 2 --> ... --> C, thread n --> D, (back to) thread 1
will deadlock when C sends a message to D, if none
of the previous wndproc's have called ReplyMessage before sending a message
to the next window. In effect, ReplyMessage breaks the chain.
Other forms of message transmission
In addition to posting with PostMessage, you might want to check out sending
with SendNotifyMessage, SendMessageTimeout, and SendMessageCallback.