Re: Terminating threads in Destructor
From: Christopher J. Holland......................................................... (msnews_at_microsoft.com)
Date: 02/10/05
- Next message: Christopher J. Holland.........................................................: "Re: Terminating threads in Destructor"
- Previous message: John Doe: "FindFirstFile, how much faster than FindNextFile?"
- In reply to: Doug Harrison [MVP]: "Re: Terminating threads in Destructor"
- Next in thread: Doug Harrison [MVP]: "Re: Terminating threads in Destructor"
- Reply: Doug Harrison [MVP]: "Re: Terminating threads in Destructor"
- Messages sorted by: [ date ] [ thread ]
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++
- Next message: Christopher J. Holland.........................................................: "Re: Terminating threads in Destructor"
- Previous message: John Doe: "FindFirstFile, how much faster than FindNextFile?"
- In reply to: Doug Harrison [MVP]: "Re: Terminating threads in Destructor"
- Next in thread: Doug Harrison [MVP]: "Re: Terminating threads in Destructor"
- Reply: Doug Harrison [MVP]: "Re: Terminating threads in Destructor"
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|