Re: Getting thread to stop in CDialog type class

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



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?

------------

****
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.
*****
What I meant was, if OnTimer is run by the same thread that handles
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. If
you had a property page, you should have said so.
I don't really know what a property page is, but looking at this link
(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.
.



Relevant Pages

  • Re: Getting thread to stop in CDialog type class
    ... presumably it does this via a PostMessage, and does not manipulate the labels directly ... manipulate windows from another thread! ... to me incorrectly waiting in OnDestroy. ... project I don't know how I can get its OnClose to activate. ...
    (microsoft.public.vc.mfc)
  • Re: Getting thread to stop in CDialog type class
    ... 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. ... manipulate windows from another thread! ... Your method of stopping the thread from OnClose seems like a perfectly ...
    (microsoft.public.vc.mfc)
  • Re: Getting thread to stop in CDialog type class
    ... presumably it does this via a PostMessage, and does not manipulate the labels directly ... manipulate windows from another thread! ... to me incorrectly waiting in OnDestroy. ... project I don't know how I can get its OnClose to activate. ...
    (microsoft.public.vc.mfc)
  • Re: [ Attn: Randy ] Ad-hoc Parsing?
    ... Though, one aspect is that LuxAsm has these "property" things (in short, as ... every label can have "child" labels in this scheme...so then constants, ... for programming (set up constants, equates and things...note, as these can ... Windows does...and then there's the "swap file" or using temporary files, ...
    (alt.lang.asm)
  • Re: Weird solid border on labels for check boxes
    ... You certainly rate your MVP designation. ... When I switched back to Windows Classic, ... > * Unaatached Labels on Tab pages. ... >> the faint border around labels for selected items, ...
    (microsoft.public.access.forms)