How to kill that MFC thread?
David J. Straley -- djs@cnj.digex.net Saturday, August 17, 1996 Environment: NT 3.51, VC++ 4.2 Hi, Can anyone offer any suggesstions on killing threads from OTHER threads? I've been spinning off new CWinThreads via AfxBeginThread(). However, I'm having problems figuring out the best way to END the "child threads" from within the "parent thread". AfxEndThread() needs to be called from within the child thread. And according to Advanced Windows NT book, trying to kill child threads from within them is "murder", which leaves the stack messed up and other potential problems with DLL's not terminating properly. Thanks! Dave Straley
Marty Fried -- mfried@linex.com Monday, August 19, 1996 [Mini-digest: 11 responses] There are two acceptable ways to end a thread from the outside, and you would use one or both, depending on the thread. One way is to use events, and have a thread that is looping wait for the event each time through the loop, with a timeout whose value depends on how long you want to delay. If the event is timed out, the loop continues, if it is set, the thread exits. Another way is to use a flag that the thread periodically checks, and when it is set, the thread ends itself. You may want to use this in combination with the first method, checking the flag periodically from within the loop. Marty Fried -----From: Sajith KumarThe book is correct. Don't kill the thread directly. Instead signal the child thread to exit by himself. You can use many methods for signaling starting from a BOOL variable. In the variable case the child thread has to poll this value frequently (Most probably at the beginning of time consuming loops) for the signal. If the parent signal the thread to exit out the function/method you are in (in the child thread). Exit the caller function/method until clear the program stack and exit normally. Never call AfxEndThread abruptly, without following the program stack. It may cause memory leak. typically ThreadF1() { ..... if(!m_b_stop) { .... } return; } ThreadF2() { ...... ThreadF1() if(!m_b_stop) { .... } return } ThreadMainFuntion() { ... ThreadF2() if(!m_b_stop) { .... } return } -------- Parent() { ..... stopThread(); .... } Sajith Kumar sajith@wallop.com 1155 Triton Drive, Suite E Foster City, CA 94404 (415) 341 1177x227 -----From: "Edgar GloWacki" My solution was to have some global var. accesable by both threads bRunThread. When I need to kill thread, I set bRunThread to FALSE from within main thread, and in a child thread i was checking bRunThread about 1 per second. When it was FALSE, I was able to kill the thread within child. I know that this looks like hack, but thats the only think I was able to come up with. maybe I will see a better solution by somebody else. Edgar GloWacki -----From: harish@wiproge.med.ge.com (Harish Nandyala) Hi Dave, There is no neat way provided by Win32 to terminate one thread from another gracefully. There is a Win32 function called TerminateThread which you can use but this mess up the stack ( as you said in your mail ). The best way to achieve this to do it yourself. WaitforSingleObject function also takes a thread handle as a parameter and the state becomes signalled when the thread completes its execution. Another way, which I used, is to have events ( something like Exit Event ). Let the parent thread set its state to signalled when it wants the child thread to terminate . The child thread should check the state of the event time to time to check if it needs to exit. I hope that this helps you ... regards -Harish -----From: "Rommel Songco" Hi there! If your child thread has a message pump and a window associated with it, you could simply post a user-defined message to that window when you want that child thread to terminate. Inside the handler for that message, call PostQuitMessage(). If your child thread is a "worker" thread, you can use events to signal whatever you like. Before you start the child thread, create the event as follows: // Create the event that will signal the thread to close. m_hCloseEvent = CreateEvent(NULL, TRUE, FALSE, NULL); Store this handle with other handles of events you're waiting for: HANDLE hEventsToWaitFor[n]; hEventsToWaitFor[0] = m_hCloseEvent; ... Then in your thread function: while (TRUE) { // wait for events to occur DWORD dwHandleSignaled = WaitForMultipleObjects(n, EventsToWaitFor, FALSE, INFINITE); // determine which event occurred switch(dwHandleSignaled) { case WAIT_OBJECT_0: // Signal to end the thread. // do some cleanup ... return 0; } To signal the child thread to quit, the parent thread can do the ff: SetEvent(m_hCloseEvent); // wait for child thread to exit properly if (WaitForSingleObject(m_hThread, 10000) == WAIT_TIMEOUT) { // child thread has not terminated; TerminateThread(m_hThread, 0); // force it to end } CloseHandle(m_hCloseEvent); The snippets of code above assume that you subclass CWinThread to suit your needs. Regards, Rommel rsongco@spectrasoft.com -----From: "Alistair Israel" You're problem is of the nature of problems known as IPC or inter-process communication. In this case, you want your parent thread to tell all its children to quit it. There are several ways of doing IPC and going about this in particular. Here's some of what I know and I've toyed around with: a) IPC via synchronization object. This can either be simple shared (global) memory or a 'real' Windows synchronization object (Mutex, Semaphore, etc.). Basically, each of your child threads checks to see the state of the synchronization object from time to time, when it becomes 'set', then the child threads should know its time to kill themselves. A global memory variable is somewhat fine as long as only one thread will be writing to it (single-writer multiple-reader). A cleaner way would be to use a Windows synchronization object such as a global CEvent, though this is just a little bit more involved. b) IPC via Windows messages/ thread messages. Yes, you can actually do this, provided your child threads do actually check their message queue (user-interface threads and threads that own windows should, but worker threads sometimes don't). The easiest way (and this is what I use mostly) goes like: PostThreadMessage(m_nThreadID, WM_QUIT, 0, 0)); Then simply do cleanup in your CWinThread's ExitInstance method. Good luck! "Walk the earth, Surf the Net" - Alistair Israel (aisrael@hotmail.com) Developer Dude Pilipino Data Network, Inc. http://202.47.133.168 [0800-2000 GMT+0800 only] --------------------------------------------------------- Get Your *Web-Based* Free Email at http://www.hotmail.com --------------------------------------------------------- -----From: Karl Lukas Look up the documentation for WaitForSingleObject(). In short, you have to do the following steps: o CreateEvent() a named event object in the parent thread o AfxBeginThread() your child thread o OpenEvent() the named event within your child thread o Periodically call WaitForSingleObject(hHandle, 0) from your child thread. AfxEndThread() from within your child thread when the event object is in signaled state. o SetEvent() the event object from your parent thread whenever you want to end your child thread. Another, quick and dirty, solution would be to periodically check the state of a shared global variable which can be set by your parent thread. Make sure to declare that variable volatile, just to be on the safe side. Hope this helps, Karl > -----From: "Hill, Les" Why not post a "quit" message to the thread? You can use a user-defined message to indicate that the thread should cleanup and exit; you could also directly post a WM_QUIT to the thread. Les Hill leh@cybercom.net -----From: Wolfgang Loch Advanced Windows NT says calling EndThread from within the thread is "suicide". But there are no problems in this case. Calling TerminateThread from outside the thread is "murder". And there you may get problems. So you should avoid it if possible. Instead you should try to notify the thread (PostThreadMessage or setting an event) to terminate itself. The problem is how to determine whether the thread is already finished, since the CWinThread object may no longer be valid. A good practice is to 1. create the thread in suspended mode 2. obtain the thread handle from CWinThread 3. resume the thread Now you can obtain the thread's state using the handle. regards, Wolfgang -- /-------------------------------------------------\ | Wolgang Loch (Technical University of Ilmenau) | | e-mail: Wolfgang.Loch@rz.TU-Ilmenenau.DE | | www : http://www.rz.tu-ilmenau.de/~wolo | \-------------------------------------------------/ -----From: Pradeep Tapadiya Look at events under Win32. If you architect your child thread such that it waits for an event and takes an active based on a directive, you can specify a TERMINATE directive that can cleanup terminate that thread. unsigned _stdcall MyThreadProc(void* p) { FOO* pFoo = (FOO*) p; for(;;) { // infinite loop DWORD retVal = WaitForSingleObject(pFoo->m_hEvent, INFINITE); if (WAIT_OBJECT_0 != retVal) { // got a problem. Deal with it. ... } switch (pFoo->m_Directive) { case TERMINATE: return 0; // Fine. I will terminate. case DO_SOMETHING: DoSomething(); ... } } // end infinite loop return 0; // we will never come here but will stop compiler warning } Hope this helps. Pradeep pradeep@nuview.com -----From: "PJ Durai" You are right. Do not kill the threads. Making them kill themselves is the best policy. This could be a possible scenario in general terms. thread 0 -------- Create a semaphore. . ( or >1 semaphore if you your threads do different things and die at different times.) Lock the semaphore(s). Fire the threads. { // probably some sort of loop. Release the semaphore if if you know that the thread's usefulness is over. } Wait on the Thread handle(s) (Just to be sure.) Other threads. ------------ While ( the semaphore is still locked. ) { Do whatever. } call afxEndThread This way your exit will be clean. Instead of semaphore you can use any thread-safe mechanism (events, objects etc). Anything but a global variable ofcourse. GoodLuck pj
| Вернуться в корень Архива |