INFO: SendMessage() in a Multithreaded Environment

ID: Q95000

The information in this article applies to:

SUMMARY

When thread X calls SendMessage() to send a message to a window created by thread Y, it must wait until thread Y calls PeekMessage(), GetMessage(), or WaitMessage() before the SendMessage() call can continue. This process prevents synchronization problems.

MORE INFORMATION

Because of the multithreaded environment of Windows NT, SendMessage() does not behave in the same manner as it does under Windows 3.1. Under Windows 3.1, SendMessage() simply calls the window procedure given to it. In Windows 3.1, if you use the SendMessage() function to send a message to a window of another task, the system will perform a task switch to the target window (change to the stack of the target Windows-based application), let the target window process the message [when it calls GetMessage() or PeekMessage()], and then switch back to the original message.

Under Windows NT, however, only the thread that created a window may process the window's messages. Therefore, if thread X sends a message [via SendMessage()] to a window that was created by thread Y, thread X must wait for thread Y to be in a receiving state, and handle the message for it.

Thread Y is only in a receiving state when it calls PeekMessage(), GetMessage(), or WaitMessage(), because synchronization problems may occur if a thread is interrupted while processing other messages. While in a receiving state, thread Y may process messages sent to its windows via SendMessage() (in this case, by thread X).

Note that PeekMessage() and GetMessage() look in thread Y's message queue for messages. Because SendMessage() does not post any messages, PeekMessage() and GetMessage() will not see any indication of the SendMessage() call. The two functions merely serve as a point in time at which SendMessage() (thread X) may "interrupt," and have thread Y process its message next. Then PeekMessage() or GetMessage() continues normal operation under thread Y.

Because of this behavior, if thread X sends a message to thread Y, and thread Y is locked in a tight loop, thread X is now locked as well. This may be prevented by using SendNotifyMessage(), which behaves as SendMessage() does above, but returns immediately. This may be an advantage if it is not important that the sent message be completed before thread Y continues. Note, however, that because SendNotifyMessage() is asynchronous, thread X should not pass pointers to any of its local variables when making the call, because they may be gone by the time thread Y attempts to look at them. This would result in a general protection violation (GP fault) when thread Y accesses the pointer.

Additional query words: GP-fault

Keywords          : kbNTOS kbGrpUser kbWinOS95 kbWinOS98 kbWndw kbWndwMsg 
Issue type        : kbinfo

Last Reviewed: December 18, 1998