Re: Getting thread to stop in CDialog type class
- From: andreas.zetterstrom@xxxxxxxxx
- Date: Mon, 16 Feb 2009 02:59:56 -0800 (PST)
On 15 Feb, 04:03, Joseph M. Newcomer <newco...@xxxxxxxxxxxx> wrote:
(1) presumably there *is* a reason to force the update. Please explain
(2) presumably it does this via a PostMessage, and does not manipulate the labels directly
Read my essay on worker threads on my MVP Tips site.
You are doing a cross-thread SendMessage, which should always be thought of as a Really
Bad Idea To Be Avoided At All Costs. Don't touch a window owned by one thread from any
other thread, period. Otherwise, the failure you see is inevitable.
Waiting in OnDestroy is a particularly poor way to deal with this, and must not be used.
You CANNOT make it work, so don't even bother trying. It is the wrong place, FAR too
late, to discover that the thread should be shut down. See my essay on worker threads.
You have to initation shutdown as a two-phase process
OnClose/OnOK/OnCancel:
if a thread is running
Tell the thread to stop
Set a flag saying you are in shutdown mode
return without calling the CDialog superclass method
thread:
When it sees it should stop, it exits its loop, then does a
PostMessage a user-defined completion message to the main thread
main thread OnThreadCompleted handler
indicate the thread has finished
if the shutdown mode flag is set, PostMessage(WM_CLOSE) to
your window to close
(Note that since there is no thread running, it will
shut down as expected)
The failure here is that you are trying to impose sequential semantics in an asynchronous
world. Generally, treat most WaitForSingleObject calls in the main thread as a design
error. You must not block the message pump. So make everything be asynchronous in the
first place, don't think about forcing waits, and the problem goes away. And NEVER
manipulate windows from another thread!
joe
On Fri, 13 Feb 2009 08:01:30 -0800 (PST), andreas.zetterst...@xxxxxxxxx wrote:
Let's see if I can explain this...
I have a class based on a standard CDialog, in it I have a thread
which loops every 100 ms. This thread has two purposes;
1) it invalidates a painting area, forcing the dialog to redraw even
if windows don't see it as nessesary
2) it updates values in various labels and such
My problem is with #2, and specifically when the app is about to exit.
At OnDestroy I have to stop the thread, as after OnDestroy has
finished the hWnds to all child labels are not usable anymore. To do
this I wait in OnDestroy for the thread to finish its current cycle
(using a semaphore), and then stop it. The problem is that writing
data to the labels is essentially sending a message to the message
queue, and the message queue is at the moment stopped in OnDestroyed
(I think), thus a deadlock! I can't for the life of me figure out how
to reliably stop the thread without this deadlock occuring.
Joseph M. Newcomer [MVP]
email: newco...@xxxxxxxxxxxx
Web:http://www.flounder.com
MVP Tips:http://www.flounder.com/mvp_tips.htm
1) I'm showing simple moving graphics with related data shown in
various CLabels and CListCtrls, which is why I need to update the
window more often than Windows wants me to.
2) I'm calling functions such as CListCtrl::InsertItem and
CStatic::SetWindowText which I assume at some level posts or sends a
message to the queue, waits for it to complete and hangs the app due
to me incorrectly waiting in OnDestroy.
Your method of stopping the thread from OnClose seems like a perfectly
good solution, and in fact I myself tried to do that, but by some
wierd reason OnClose is never called in my app. I have traced it down
to the main CFormView, and as it is part of the base of the MFC
project I don't know how I can get its OnClose to activate. That is
why I was using OnDestroy as it was the only message that actually was
reliably called. So I guess this is another obstacle I have to
overcome.
Just to clarify: My app is an MFC application, single document,
created by the wizard. In the main CFormView I create a CTabView
derived class, which itself then creates a number of tabs which are
realized by CDialog derived classes where the OnOk and OnCancel bodies
have been emptied, the buttons deleted and the class being defined as
a child (as I can see you yourself do in your examples). In OnClose in
CFormView I call CTabView::CloseWindow and in CTabView's OnClose I
call CloseWindow for the CDialogs. But as I never get the OnClose from
CFormView of course none of the others are called either.
About the closing of the thread (or timer as I guess it should be
instead); why do I have to post a user defined message and then when
receiveing that message posting WM_CLOSE? can't I post WM_CLOSE
directly from the thread/timer as it finishes for the last time?
------------
****What I meant was, if OnTimer is run by the same thread that handles
And your point is? So what? First, OnTimer does *not* "send" a message to the queue; nor
does it "post" a message. What happens is that if the timer goes off, the next time
GetMessage discovers that there is nothing in the queue it simulates the receipt of a
timer message.
*****
the messages, won't it deadlock itself if I somewhere in the OnTimer
function tries to post a new message? as through CListCtrl::InsertItem
or CStatic::SetWindowText?
You said you had a dialog. So either you have a dialog, or you have a property page. IfI don't really know what a property page is, but looking at this link
you had a property page, you should have said so.
(http://msdn.microsoft.com/en-us/library/675f1588(VS.80).aspx) I'm
pretty sure a CDialog derived class with the OnOk and OnCancel bodies
emptied is much closer to a CDialog than a property page.
Thanks for the input. I'm definitely going to bookmark your tips page.
.
- Follow-Ups:
- Re: Getting thread to stop in CDialog type class
- From: Joseph M . Newcomer
- Re: Getting thread to stop in CDialog type class
- References:
- Getting thread to stop in CDialog type class
- From: andreas . zetterstrom
- Re: Getting thread to stop in CDialog type class
- From: Joseph M . Newcomer
- Getting thread to stop in CDialog type class
- Prev by Date: Re: CWnd::??? -> ??? -> CFontDialog -> CreateFontIndirect -> CWnd::SetFont()
- Next by Date: MFC-extension DLL : initialization function
- Previous by thread: Re: Getting thread to stop in CDialog type class
- Next by thread: Re: Getting thread to stop in CDialog type class
- Index(es):
Relevant Pages
|