- Is SendMessage from worker thread really evil?
- Posted by Robin Lavallee on July 29th, 2004
Hello,
I've read countless times that sending messages to a control from a thread
that doesn't own it is a really bad practice.
I've noticed this myself when I ran into hair pulling deadlocks when doing
such. However, I've noticed as well that those deadlocks were created
because I would hang the main GUI thread while waiting for an event and
forgetting about the message pump.
Question:
If you make sure that you never stall the message pump in the GUI thread, is
using SendMessage from worker thread really that evil? For example, I had
deadlocks because I was using WaitForSingleObject, when I changed it to
MsgWaitForMultipleObjects, all went fine.
As far as I can tell, using the worker thread to manipulate the controls is
usually simplier. The deadlock ALWAYS seems to come from the fact that the
message pump has been stopped. Logically, the evilness seems to come from
the fact that people hang the GUI thread.
Can't we move the evilness from "Never send message controls from the worker
thread" to "Never stall the message pump" and let people happily use
SendMessage from their worker threads?
Robin Lavallée
- Posted by Stephen Kellett on July 29th, 2004
In message <El8Oc.14412$Vp1.70521@weber.videotron.net>, Robin Lavallee
<robin.lavallee@videotron.ca> writes
Yes. DO NOT DO THIS. EVER.
Yes. Do not do it.
No. Use PostMessage instead, or redesign your application.
Stephen
--
Stephen Kellett
Object Media Limited http://www.objmedia.demon.co.uk
RSI Information: http://www.objmedia.demon.co.uk/rsi.html
- Posted by Flzw on July 29th, 2004
Oh yeah ? and how to you pass pointers then ? it gets needlessly
complicated, there is no real reason not to use SendMessage as long as the
UI thread never waits for the calling thread, at least that's what I
understood reading msdn and it's been working nice for me.
Now I admit I am no expert but my app runs fine, and it would require more
work to use PostMessage.
- Posted by Tim Robinson on July 29th, 2004
Flzw wrote:
SendMessage between threads is effectively PostMessage plus a wait. If the
destination thread isn't processing messages, then the calling thread will
wait until it does. If the destination thread is waiting on the calling
thread -- not an uncommon occurrence -- then you've got a deadlock.
The better solution is to define a private (WM_APP + n) message whereby the
sender allocates memory, passes it through lParam, and the recipient frees
it.
--
Tim Robinson (MVP, Windows SDK)
http://mobius.sourceforge.net/
- Posted by Scott McPhillips [MVP] on July 30th, 2004
Robin Lavallee wrote:
But you should stall the message pump, typically on WM_CLOSE, to wait
for the worker thread to terminate.
The real problem is that "never stall the message pump" is not a robust
solution under future maintenance, and the problems that can be caused
by a SendMessage deadlock are damn near impossible to test for. They
tend to deadlock only after you release the program to an important
customer. "Here be dragons."
--
Scott McPhillips [VC++ MVP]
- Posted by Severian on July 30th, 2004
On Thu, 29 Jul 2004 11:04:04 -0400, "Robin Lavallee"
<robin.lavallee@videotron.ca> wrote:
I will echo the other responses.
DO NOT DO THIS.
Sometimes problems will only appear on multi-processor machines.
Sometimes problems will occur only very rarely.
Sometimes problems will happen only with specific control types.
Also, it's quite easy to avoid! Use PostMessage; you can pass pointers
to static or heap-allocated structures.
--
Sev
- Posted by Sam Jost on July 30th, 2004
"Robin Lavallee" <robin.lavallee@videotron.ca> wrote:
Using SendMessage from a worker thread is a lurking evil. It will run on
your machine, it will mostly run on others people's machines, too, but every
few hundred calls later it will bring the most annoying of bugs, sometimes
out in the open, sometimes hidden ones.
And the day you start that program on a *real* multi-CPU computer all hell
will break loose.
It does work. mostly. And if you don't mind connecting your program with the
words 'unreliable' and 'unstable' it should be no problem at all.
Sam
- Posted by Martin Aupperle on August 2nd, 2004
On Thu, 29 Jul 2004 11:04:04 -0400, "Robin Lavallee"
<robin.lavallee@videotron.ca> wrote:
That is one way to make a program nonresponsive.
What, for example, happens when you send your control a message which
in turns triggers some other innocent message(s) which trigger some
behavior that - maybe after some more steps - make the thread send
another message to the control, etc.
Sure - this is rare, and maybe if the system is fast enough (i.e. you
developer machine), does not lead to problems. But on a slow machine
(i.e. at the customer's site) it chokes.
I once had this when I tried to do some lengthy database lookups on
the input of a control. The lookup was in a thread and every change of
the control triggered it. Nasty!
Such things are a nightmare to debug, because of the timing involved.
Nondeterministic behavior! No gain in anything can outweight the
potential problems lurking here.
------------------------------------------------
Martin Aupperle
------------------------------------------------