Multiple threads, SendMessage(), and PostMessage()
Paul E. Jones -- paulej@acm.org
Wednesday, November 27, 1996
Environment: VC++ 4.1, Win 95
Suppose I have two threads:
T1 - The main thread which processes windows messages
T2 - A worker thread which does not process messages
Suppose that T2 needs to cause T1 to take some action. If I wish to send a
message from T2 to T2 using SendMessage(), what happens exactly? My
understanding was that T2 would block and the next time T1 entered the
message processing loop it would handle the message, causing T2 to unblock
and continue.
However, I was reading "Inside Vistual C++" by David J. Kruglinski
(Microsoft Press, 1995) and on page 253, it reads:
"Do you send a message or post it? Better to post it because sending it
could cause reentry of the main thread's [T1] MFC message pump code, and
that would create major problems."
Now, exactly *how* can issuing a SendMessage() call cause reentry into the
message pump? Am I correct in thinking that when a SendMessage() is called
from T2 that T2 will block until T1 handles the message?
Thanks,
Paul E. Jones
// Paul E. Jones
// paulej@acm.org * http://members.iglou.com/paulej/
// PGP public key available by e-mail or my WWW page
// Key fingerprint = 28 02 6D 1F 20 AE 9F 82 43 02 DD 02 0C 00 3C 65
Rajesh Babu T -- rbabu@hotmail.com
Friday, November 29, 1996
>Environment: VC++ 4.1, Win 95
>
>Suppose I have two threads:
>T1 - The main thread which processes windows messages
>T2 - A worker thread which does not process messages
>
>Suppose that T2 needs to cause T1 to take some action. If I wish to send a
>message from T2 to T2 using SendMessage(), what happens exactly? My
>understanding was that T2 would block and the next time T1 entered the
>message processing loop it would handle the message, causing T2 to unblock
>and continue.
>
>However, I was reading "Inside Vistual C++" by David J. Kruglinski
>(Microsoft Press, 1995) and on page 253, it reads:
>
>"Do you send a message or post it? Better to post it because sending it
>could cause reentry of the main thread's [T1] MFC message pump code, and
>that would create major problems."
>
>Now, exactly *how* can issuing a SendMessage() call cause reentry into the
>message pump? Am I correct in thinking that when a SendMessage() is called
>from T2 that T2 will block until T1 handles the message?
>
>Thanks,
>Paul E. Jones
Hi Jones,
Yes, U are right.
If the specified window was created by the calling thread, the window procedure
is called immediately as a subroutine. If the specified window was created by a
different thread, Windows 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. The sending thread is blocked
until the receiving thread processes the message.
bye,
---------------------------------------------------------
Get Your *Web-Based* Free Email at http://www.hotmail.com
---------------------------------------------------------
Dong Chen -- d_chen@ix.netcom.com
Thursday, November 28, 1996
>
>Now, exactly *how* can issuing a SendMessage() call cause reentry into the
>message pump? Am I correct in thinking that when a SendMessage() is called
>from T2 that T2 will block until T1 handles the message?
>
>Thanks,
>Paul E. Jones
>
>
For your first question, you can find the answer from Jeffrey Richter's
Advanced Windows NT in the chapter about thread queues and message
processing, or from MSDN CD (there are several articles about this topic).
For the second one, you are right. T2 has to wait until T1 processed the
message and returned. But T1 will get T2's message only when it is ready to
enter the get/pump message cycle.
Mike Blaszczak -- mikeblas@nwlink.com
Friday, November 29, 1996
At 00:48 11/27/96 -0500, Paul E. Jones wrote:
>Environment: VC++ 4.1, Win 95
>Suppose I have two threads:
> T1 - The main thread which processes windows messages
> T2 - A worker thread which does not process messages
Maybe you should spawn a third thread:
T3 - Judgement Day
to clean up after everything is over.
>Suppose that T2 needs to cause T1 to take some action. If I wish to send a
>message from T2 to T2 using SendMessage(), what happens exactly?
I'll assume that you meant that you want to send a message from T2 to T1,
not from T2 to itself.
Here's what happens:
1) T2 calls SendMessage(). That means that T2 has
entered the Windows Kernel. Windows figures out what's
going on, and decides to block T2.
2) Windows puts the message into the queue that T1 is using.
3) Eventually, the Windows scheduler gets around to scheduling again
the execution of T1. Eventually, T1 will get into its message
loop. It'll make a call like PeekMessage() or GetMessage().
4) Windows will see that T1 is making such a call, and note that it
has a pending sent message to be processed. During the call to
one of those queue management functions, Windows will directly
call the window proc handling the window that was targeted
by the send message.
5) The call runs. Maybe the Windows scheduler,
during this time, decides to suspend T1 and resume it again.
It certainly won't resume T2. T1 returns from the call.
6) T2, having the return value from the call, gets resumed.
The surprises here are that:
+ the message loop doesn't actually get sent messages back
from GetMessage().
+ Windows sometimes secretly calls window procs for you
directly without you calling DispatchMessage().
Many people don't know these things, though they are covered in the
overviews and in the related function documentation if you read it
carefully.
>My understanding was that T2 would block and the next time T1 entered the
>message processing loop it would handle the message, causing T2 to unblock
>and continue.
In a nutshell, yeah.
>However, I was reading "Inside Vistual C++" by David J. Kruglinski
>(Microsoft Press, 1995) and on page 253, it reads:
>
>"Do you send a message or post it? Better to post it because sending it
>could cause reentry of the main thread's [T1] MFC message pump code, and
>that would create major problems."
This is just wrong.
It's better to decide wether you need it processed
_right now_ and you need the return value back OR if you just need the
action to happen sometime later and don't care when, or that you don't
don't care about the return value. Maybe you know you need
to use SendMessage() because one of your message parameters is a pointer.
What I'm trying to say is that "reentry of the main thread's message pump
code" is the least of your worries. I can't even guess what "reentry of
the main thread's message pump code" is really supposed to mean, but it
sounds like something that wasn't completely understood or misedited before
making it into the book.
>Am I correct in thinking that when a SendMessage() is called
>from T2 that T2 will block until T1 handles the message?
Yep.
.B ekiM
http://www.nwlink.com/~mikeblas/
I'm afraid I've become some sort of speed freak.
These words are my own. I do not speak on behalf of Microsoft.
Mario Contestabile -- Mario_Contestabile.UOS__MTL@UOSMTL2.universal.com
Friday, November 29, 1996
>Suppose I have two threads:
> T1 - The main thread which processes windows messages
> T2 - A worker thread which does not process messages
>
>Suppose that T2 needs to cause T1 to take some action. If I wish to send a
>message from T2 to T2 using SendMessage(), what happens exactly? My
>understanding was that T2 would block and the next time T1 entered the
>message processing loop it would handle the message, causing T2 to unblock
>and continue.
If T1 does a SendMessage to T2 and when T2 is responding to the T1 message it
does
a SendMessage to T1, it will result in dead lock. Better to use
SendNotifyMessage.
mcontest@universal.com
Gerald Alter -- jalter@alt-ego.com
Sunday, December 01, 1996
Or... if it is not imperative to have the message processed immediatly,
send do a PostThreadMessage to the thread you want. The SendMessage()
function will cause the thread which called the SendMessage function to
halt execution until it recieves a true or false return. This is NOT
recommended for Thread interaction. Threads can be recursed into, BUT,
each and every call to the SendMessage will halt until it recieves the
appropriate return value. The recommended way of communication between
threads it definatly to use the PostThreadMessage function. Albiet, this
does require a little more coding on your part to make your Thread message
aware. Good luck.
Jay Alter
FASA Interactive
jalter@alt-ego.com
----------
> From: Mario Contestabile
> To: Paul E. Jones
> Cc: mfc-l
> Subject: Re: Multiple threads, SendMessage(), and PostMessage()
> Date: Friday, November 29, 1996 8:52 AM
>
> >Suppose I have two threads:
> > T1 - The main thread which processes windows messages
> > T2 - A worker thread which does not process messages
> >
> >Suppose that T2 needs to cause T1 to take some action. If I wish to
send a
> >message from T2 to T2 using SendMessage(), what happens exactly? My
> >understanding was that T2 would block and the next time T1 entered the
> >message processing loop it would handle the message, causing T2 to
unblock
> >and continue.
>
> If T1 does a SendMessage to T2 and when T2 is responding to the T1
message it
> does
> a SendMessage to T1, it will result in dead lock. Better to use
> SendNotifyMessage.
>
> mcontest@universal.com
Mike Blaszczak -- mikeblas@nwlink.com
Tuesday, December 03, 1996
At 19:30 12/1/96 -0500, Gerald Alter wrote:
>Or... if it is not imperative to have the message processed immediatly,
>send do a PostThreadMessage to the thread you want. The SendMessage()
>function will cause the thread which called the SendMessage function to
>halt execution until it recieves a true or false return. This is NOT
>recommended for Thread interaction.
Of course it's recommended: it's a very inventive way to synchronize your
threads. It's at the hub of thread model marshalling in OLE automation;
that is, Windows uses it itself.
If thread A is playing with a resource, and it needs thread B to play
with the resource, too, thread A can send thread B a message to ask it to
do that work. Since thread A is blocking until thread B returns from
processing that message, it's guaranteed that both threads won't touch
the object in question (if that message handler is the only place thread
B has access to the resource in question).
This can be simpler and more natural than setting up idle loops that work
with other inter-thread communications mechanisms.
Just like anything else, inappropriately using this technique causes
inefficient execution and cancer in lab animals. But I think it's
inappropriate to say that this "isn't recommended".
.B ekiM
http://www.nwlink.com/~mikeblas/ <-- trip report central!
95 Honda VFR-750F / 88 Yamaha FZ-700 (damaged) / 94 Mazda RX-7
Serial #00050! / AMA - HRC - VFROC / Wang Dang Wankel
I am bored of this talk. It is time now for the dancing!
These words are my own - I do not speak on behalf of Microsoft.
| Вернуться в корень Архива
|