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.
| Вернуться в корень Архива |