Re: Terminating threads in Destructor

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

From: Christopher J. Holland......................................................... (msnews_at_microsoft.com)
Date: 02/10/05


Date: Wed, 9 Feb 2005 22:10:58 -0800

Thanks a bunch,

>>I noticed the CEvent Class. Should I be using that?
> There are numerous design flaws in the MFC sync classes, so I reflexively
> hesitate to recommend them.
I feel like I am hacking sometimes. I use what works. Might not be perfect,
but it works.
Then, I get myself into trouble...

I am a bit confused about CStrings.
Normally I just do SomeFunction(CString String) and pass the whole CString
Object.
I've gotten breaks for some odd reason, so I changed it.
I've have never used const, maybe I should be?
I changed it to SomeFunction(CString& String) to just pass a pointer to
make it quicker?
Then, I changed it to SomeFunction(LPSTR String). Well, now I have to change
the way
I send strings to cast it as a CString. i.e. SomeFunction((CString)"Test
Message");
Lord only knows what the hell I am doing. The code I see in MFC does it that
way.
Then I see LPCSTR and LPWSTR.
Well, that is for another post... [ It works for now:) ]

I think my basic thread design is flawed, because I am calling functions
from the Main thread.
I should move all the necessary functions to the Thread class.
I think a better design would be for the thread to have some function called
CopyData(), then let the thread do it's work.
After the thread has finished it's work, it would post a message to the main
thread saying "Data is Ready",
then the Main thread would do a CopyData() from the thread.
Then, at the end of program, I just post a Quit Message, and not have to
worry about when the thread terminates.
The Secondary Thead should be as totally indepedent of the Main Thread as it
can be.

I am going to have to read the links and do some more investigating
tomorrow.

-- 
Christopher J. Holland [!MVP]
http://www.mvps.org/vcfaq/
http://www.codeguru.com
http://www.codeproject.com
http://www.naughter.com/
http://support.microsoft.com/default.aspx
http://msdn.microsoft.com/howto/
http://msdn.microsoft.com/library/
www.flounder.com/mvp_tips.htm
"Doug Harrison [MVP]" <dsh@mvps.org> wrote in message 
news:icel01dt597hv2cd2rq1h4d4km3f0uiuud@4ax.com...
> Christopher J.
> Holland...........................................................................................................
> wrote:
>
>>Hi,
>>
>>I got threads working, now I would like to know how to terminate them on
>>close.
>>
>>>From what I have been told, It is a bad idea to halt the main thread.
>
> It's bad to halt an UI thread indefinitely while the UI should remain
> responsive. Provided the thread you're asking to close is designed to
> respond promptly to termination requests, and assuming there's no deadlock
> potential, there's nothing wrong with doing WFSO(INFINITE) in the man
> thread. In fact, when you can't logically proceed with what you were doing
> until the thread exits, that's the best way to do it. I always try to 
> design
> things so this is possible.
>
> The alternative is for the main thread to detect the thread termination
> asynchronously so it can resume what it would like to have been doing
> sequentially, which introduces a sort of distributed state that can be 
> hard
> to manage. I've heard it recommended that the secondary thread should
> PostMessage an "I've terminated" message to the main thread, but this
> implies the main thread will drop back into its message loop in the 
> interim.
> This brings the whole program into play, which might invalidate your
> nominally sequential algorithm unless you take measures to limit your UI
> while you're waiting. This asynchronous approach is thus most appropriate
> when you don't do anything in response to the message except to wait on 
> the
> thread handle and clean up. Furthermore, before it exits, the main thread
> still has to wait forever on extant threads, including those whom it's 
> asked
> to quit but who haven't yet posted back that they have. During this period
> of secondary thread limbo, I think it's rather uncool to close a window 
> that
> by design is a target for messages from your threads, so you better keep
> your window and message loop going while you're waiting. You could
> accomplish this by replacing WaitForXXX with a local message loop that
> retrieves the custom messages. Doing the asynchronous approach _right_ 
> takes
> a fair amount of work, and I use it only as a last resort.
>
>>I kind of have to do that to wait for the thread to terminate.
>>I'm not sure what else I should be doing?
>>I am using Events to Start and Terminate a thread.
>>I have just been hacking and not really sure about the exact way.
>>Right now, I am using
>>   HANDLE m_EventSomething
>>and
>>  SetEvent( m_EventSomething);
>>
>>I noticed the CEvent Class. Should I be using that?
>
> There are numerous design flaws in the MFC sync classes, so I reflexively
> hesitate to recommend them. However, they do provide more or less correct
> C++ object semantics WRT construction, destruction, and exception safety, 
> so
> they're probably better than the raw API, which you should still 
> understand
> so that you can recognize where MFC goes wrong. Off the top of my head, 
> MFC
> conflates CRITICAL_SECTION with kernel objects, and it allows passing a
> CCriticalSection object to CMultiLock, which becomes a runtime error as 
> you
> can't WFMO on a CRITICAL_SECTION. A CSingleLock by default does not 
> acquire
> the sync object in its default ctor, which is unhelpful. The
> CSingleLock::Lock function returns BOOL, even though it wraps WFSO, which
> can return one of four different values. It's possible to specify a 
> timeout
> for a CCriticalSection, even though it doesn't work. And so forth.
>
>>//-------------------------------------------------------------------------------------------------------------------------------------------------------------
>>// Destructor
>>//-------------------------------------------------------------------------------------------------------------------------------------------------------------
>>CSomething::~CSomething()
>>{
>>  m_pFFTThread->TerminateThread();   //Sets m_bTerminateThread so it will
>>die.
>
> That's a very scary name for a thread member function. It makes me think 
> of
> this:
>
> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/terminatethread.asp
>
> Also, a variable named "m_bTerminateThread" suggests you're using a bool 
> to
> control thread termination, which is not the best way. You ought to be 
> using
> an event. More below.
>
>>  m_pFFTThread->SetThreadEvent();    //Enable the thread. (In case nobody
>>else has)
>>  DWORD DWord = WaitForSingleObject(m_hEventThreadTerminate, INFINITE);
>>//Wait before we delete buffers
>>}
>>
>>
>>//-------------------------------------------------------------------------------------------------------------------------------------------------------------
>>// Thread
>>//-------------------------------------------------------------------------------------------------------------------------------------------------------------
>>CFFTThread::Run()
>>{
>>  do
>>  {
>>  ResetEvent(m_hEvent); //After we finish one loop, reset and wait to be
>>signaled
>>  WaitForSingleObject(m_hEvent,INFINITE); //Wait to be signaled
>
> After you replace m_bThreadTerminate with a manual-reset event, you should
> replace this WFSO with a WaitForMultipleObjects that puts the quit-event
> first in the handle array. See this message for more:
>
> http://groups-beta.google.com/group/microsoft.public.vc.mfc/msg/430fb37711fbf662
>
>>  m_pFFT->DoStuff();
>>  ::PostMessage(m_pFFT->GetHwnd(), m_pFFT->GetWParam(), 
>> m_pFFT->GetLParam(),
>>0); //To Draw Stuff (Don't worry, it works)
>> }while (!m_bThreadTerminate);
>>
>> //Thread is finished, so Turn off.
>> m_pFFT->SetThreadTerminateEvent(); //Set Event in Main Thread to Signal 
>> end
>>of thread.
>> return 0;
>>}
>
> This is kind of backwards. The main thread should set the quit-event to
> indicate to the thread that it should exit. The main thread would then
> detect the thread has exited by finding the thread handle signaled. The
> event you're setting with the m_pFFT->SetThreadTerminateEvent() call 
> really
> accomplishes nothing that can't be done more robustly with the thread
> handle, which automatically becomes signaled when the thread exits. This 
> is
> explained more in the message I linked to above:
>
> http://groups-beta.google.com/group/microsoft.public.vc.mfc/msg/430fb37711fbf662
>
> -- 
> Doug Harrison
> Microsoft MVP - Visual C++ 


Relevant Pages

  • Telnet, was: Re: USS misuse
    ... This was by design. ... The responses of the three telnet address spaces we have varied wildly! ... third one also started to terminate, but never 'blocked' OMVS shutdown, so it ...
    (bit.listserv.ibm-main)
  • Re: Hobbie Cad/CNC software recommendations
    ... is that the kids come up with a design idea, Dad winds up cutting it out ... I figure once we get over the learning curve of the software then banging ... modeling program with a lot of nice features. ... I'm going to shoot for so if you want to recommend a simple one and then ...
    (rec.crafts.metalworking)
  • Re: List Box Madness
    ... There is an old adage in the design of database systems that goes ... The primary key of the Company table should appear in the ... able to create a CompanyLocation record when you have a corresponding ... I recommend a Find Company: combobox in the header of your form. ...
    (microsoft.public.access.gettingstarted)
  • Re: IJ Pinball Price???
    ... new game's design style (though it may be completely different, ... I'm not a big fan of POTC, as it is way too much stop+go type game ... I would recommend waiting til some info comes out on IJ. ...
    (rec.games.pinball)
  • Re: Linking tables with MS Access functions
    ... very poor performers since they will usually force table scans vs. the use ... will recommend them when needed. ... instead of Design View. ... This Design-view restriction has been present since ...
    (microsoft.public.access.queries)