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.