Sleeping a Primary Thrd Sleeps the secondaries????
prmslick -- prmslick@infi.net Sunday, February 18, 1996 This is a follow-on to my previous post regarding killing a secondary thread. My problem was that I couldn't be assured that my secondary thread actually shutdown. Much of my problem was in a programming mistake in that I forgot to check the status in my while loop. This code was corrected (as follows) after the mistake was pointed out by a fellow listserver lurker. My new problem is that I can't find a way to "wait" long enough for the secondary thread to end. My stategy was to post a flag (now protected with mutex's) so that the secondary thread could see the "die" indicator and shutdown in an orderly fashion with "AfxEndThread". My new problem is that the seconday thread checks for the presense of the flag at the top and bottom of a neverEnding for loop. This allows the loop to finish it's critical tasks before ending. The strategy was for the primary (app) thread to set the flag, and sit in a while loop until ::GetExitCodeThread showed that the secondary thread quit. Initially, the primary while loop was running so fast, that the secondary thread seemed never to get any cycles to do it's thing. I placed a Sleep in the primary while loop, short at first, then as long as 5 seconds to wait for the secondary thread to do it's thing. To my surprise, the Primary Sleep, seems to put the secondary thread to sleep too. I have a status window, that is updated by both threads. Up until the primary while loop (in the code below) the secondary thread is updating the window reguarly. As soon as the primary while loop (while Still_Active) starts, only the primary loop echo's a status. This happens regardless of whether I Sleep 25ms or 5000ms. Does, Sleeping in the primary thread always put all secondary threads to sleep? If so, how does one block or sleep a primary thread and still allow background processes to go? Given my present delima, can anyone give me some advice regarding how to shutdown a secondary thread, and be assured it is shutdown before continuing? //Primary Thread, Trying to shutdown secondary Thread void CWinctr555View::OnDevicecontrolEndthread() { DWORD dwStatus; if (m_pctrdevice) { if (m_pctrdevice->m_pfReadPortThread != NULL) { AfxMessageBox("Thread Pointer != NULL"); VERIFY(::GetExitCodeThread(m_pctrdevice->m_pfReadPortThread->m_hThread, &dwStatus)); if (dwStatus == STILL_ACTIVE) { AfxMessageBox("Thread Running, attempting to halt"); // Set TimeToExit Flag m_pctrdevice->m_SetCommandThreadEnd(); // The never ending Loop while(dwStatus == STILL_ACTIVE) { // Just a little status monitoring here, not // significant if (m_pctrdevice->m_pCWnd) { char *sp = "QuitLoop"; while(*sp && m_pctrdevice->m_pCWnd) m_pctrdevice->m_pCWnd->SendMessage(C555_WM_ONDEVICE_IN_CHAR, *sp++, lColorDeviceIn); } VERIFY(::GetExitCodeThread( m_pctrdevice->m_pfReadPortThread->m_hThread, &dwStatus)); Sleep(5000); // Trying to give secondary thread a // chance to quit } AfxMessageBox("Halted Thread"); m_pctrdevice->m_pfReadPortThread = NULL; } else { AfxMessageBox("Thread says it wasn't running"); m_pctrdevice->m_pfReadPortThread = NULL; } } } else AfxMessageBox("Device communications not established. Start device"); } prmslick@infi.net Using Pegasus Mail Win95 and OS2 Warp
Mike Blaszczak -- mikeblas@interserv.com Monday, February 19, 1996 [Mini-digest: 4 responses] On Sun, 18 Feb 1996, "prmslick"wrote: >This is a follow-on to my previous post regarding killing a secondary >thread. My problem was that I couldn't be assured that my secondary thread >actually shutdown. I'm not sure I saw your original note, but... >The strategy was for the primary (app) thread to set the flag, and sit in a >while loop until ::GetExitCodeThread showed that the secondary thread quit. Why don't you call WaitForSingleObject() against the handle of the thread you're waiting for? A thread handle is unsignalled while the thread is running (or suspended) and is signalled when the thread terminates. .B ekiM -- TCHAR szDisc[] = _T("These words are my own; I do not speak for Microsoft."); -----From: John Addis It seems to me that you're making this harder than it needs to be. 1) Main thread, to start shutdown: SetEvent( g_hevTerminate ); // Some event that the worker thread knows WaitForSingleObject( hThreadWorker, WAIT_INFINITE ); 2)Worker thread in its processing loop: while( !bDone ) { ... DWORD dw = WaitForSingleObject( hevTerminate, bContinue = (WAIT_OBJECT_0 == dw || WAIT_FAILED == dw); } This is actually oversimplified. For example you'd want to do better error checking as well as account for the possibility that the thread isn't running, etc. You'd probably also *not* want to use WAIT_INFINITE just in case something goes very foul in the worker thread. If it is possible for the worker thread to terminate through other means I would also suggest that you create it suspended and then duplicate the CWinThread::m_hThread handle via the DuplicateHandle API. Especially since premature termination can cause your CWinThread* to be invalid. -- John Addis Master of Time and Space jaddis@erols.com C++, MFC, Win32, Win95, TCP/IP "Invalid or missing REALITY.COM Universe halted." -----From: "Mukesh Prasad [Development Contractor]" > the secondary thread to do it's thing. To my surprise, the Primary Sleep, > seems to put the secondary thread to sleep too. I have a status window, that > is updated by both threads. Up until the primary while loop (in the code > below) the secondary thread is updating the window reguarly. As soon as the > primary while loop (while Still_Active) starts, only the primary loop echo's a > status. This happens regardless of whether I Sleep 25ms or 5000ms. If your "status window" is owned by the primary thread, the updates by the secondary thread won't be visible until the primary thread's message loop gets called. Try adding a "while (PeekMessage) {DispatchMessage}" sequence before your "Sleep", to see if this is the problem. -----From: Marty Fried At 02:05 AM 2/18/96 +0000, prmslick wrote: >This is a follow-on to my previous post regarding killing a secondary thread. >My problem was that I couldn't be assured that my secondary thread actually >shutdown. Much of my problem was in a programming mistake in that I forgot to >check the status in my while loop. This code was corrected (as follows) after >the mistake was pointed out by a fellow listserver lurker. My new problem is >that I can't find a way to "wait" long enough for the secondary thread to end. >My stategy was to post a flag (now protected with mutex's) so that the >secondary thread could see the "die" indicator and shutdown in an orderly >fashion with "AfxEndThread". My new problem is that the seconday thread checks >for the presense of the flag at the top and bottom of a neverEnding for loop. >This allows the loop to finish it's critical tasks before ending. > . . . I'm not sure about the Sleep question, but it seems like you'd be better off using WaitForSingleObject(), using the thread handle to wait for: WaitForSingleObject(m_pctrdevice->m_pfReadPortThread->m_hThread, ...). You can set a timeout for how long to wait if you want to do other processing, or somehow take some action if it times out. Of course, if you are correct about the Sleep problem, it may be that this would have the same behavior. I'd be interested to hear more about this from anyone who may be more knowledgeable. _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ Marty Fried (mfried@linex.com) Marin County, California
Mark F. Fling -- mfling@mail.stratacorp.com Monday, February 19, 1996 "prmslick"wrote: >This is a follow-on to my previous post regarding killing a >secondary thread. My problem was that I couldn't be assured that my >secondary thread actually shutdown. Much of my problem was in a >programming mistake in that I forgot to >My new problem is that I can't find a way to "wait" long enough for >the secondary thread to end. My stategy was to post a flag (now >protected with mutex's) so that the secondary thread could see the >"die" indicator and shutdown in an orderly fashion with >"AfxEndThread". My new problem is that the seconday thread checks >for the presense of the flag at the top and bottom of a neverEnding >for loop. This allows the loop to finish it's critical tasks before >ending. You're making more work than you have to. Spinning on a thread completion flag is not good multithreading practice. It's more elegant to relinquish control back to the operating system to allow efficient dispatching to other processes and threads. The way you do this is using critical sections to guard shared data access and WaitForxxxObject for semiphores, threads, and mutexes. Also, I'm wary of killing threads externally in all but the most dire situations - I recall an admonition somewhere about resources still being locked until the parent process is terminated. Yuck. My two cents: 1) In your main thread WinApp class declare a member as HANDLE m_hevntWorkCancel. 2) Initialize this semiphore using: m_hevntWorkCancel = ::CreateEvent(NULL, TRUE, FALSE, NULL)); 3) Start your worker thread using: m_thrdWork = AfxBeginThread((AFX_THREADPROC)WorkThread, (LPVOID)this, THREAD_PRIORITY_NORMAL); 4) If you need to terminate it early, say your user interface contains a Cancel button, kill the worker thread from your main thread using: if (::WaitForSingleObject(m_thrdWork.m_hThread, 0) == WAIT_TIMEOUT) ::SetEvent(m_hevntWorkCancel); The above statement checks if the worker thread is executing, and if so, posts the "cancel" semiphore. Your worker thread is probably executing some form of "loop", and a check should be made in the loop to see if the cancel semiphore posted the thread performs an orderly terminate and return with a error code, i.e.: DWORD WINAPI WorkThread(LPVOID pParam) { CMyApp pApp = (CMyApp*)pParam; do { okay, let's defrag that 10G disk array .... } while (::WaitForSingleObject(pApp->m_hevntWorkCancel, 0) == WAIT_TIMEOUT); return NO_ERROR; } 5) On your way out of your main thread, simply put the following in your ExitInstance: ::WaitForSingleObject(m_thrdWork.m_hThread, TRUE, INFINITE); ::CloseHandle(m_hevntWorkCancel); The ::CreateThread call contained within the CWinThread class returns a HANDLE suitable for waiting. These handles will signal when the thread completes. If the worker thread is complete, the above call will blow through, no sweat. If it's still continuing to terminate (maybe it's real slow dying), the main thread will wait until it completes. As to your problem with primary and worker threads locking up, without seeing your worker thread code, there's no way to determine if there's a deadlock somewhere. Sounds like it, though.
Mark F. Fling -- mfling@mail.stratacorp.com Tuesday, February 20, 1996 [Mini-digest: 2 responses] My last reply introduced more work than was necessary. I recommended using a semaphore for the main thread to post indicating a "cancel" to the worker thread. Way overkill. A shared BOOL is sufficient for this type of interthread signalling as long as it is declared "volatile" (preventing enregistering optimization). You can dispense with all that "m_hevtWorkCancel" stuff and replace it with simply "m_bWorkCancel" instead. In my haste I clipped this from a worker thread that looped on both a negative cancel and positive asynchronous printer event. Since the printer event had to be a semaphore, I figured I'd make the cancel one too and use one call - WaitForMultipleObjects. Guily as charged of criminal code bloat. -----From: "Pierre De Boeck""prmslick" wrote: >... >Given my present delima, can anyone give me some advice regarding how >to shutdown a secondary thread, and be assured it is shutdown before >continuing? >... A clean way to do that is to use the win32 API synchronisation function WaitForSingleObject(hMySecondaryThread,...). This call will block the calling thread (namely your primary thread) until the synchro object is signaled. In that case, the synchronisation object is the secondary thread and signaling means that it is shutdown.
Peter Olesen -- peter.olesen@mailbox.swipnet.se Monday, February 19, 1996 At 02:05 1996-02-18 +0000, prmslick@infi.net wrote: >This is a follow-on to my previous post regarding killing a secondary thread. >My problem was that I couldn't be assured that my secondary thread actually >shutdown. Much of my problem was in a programming mistake in that I forgot to >check the status in my while loop. This code was corrected (as follows) after >the mistake was pointed out by a fellow listserver lurker. My new problem is >that I can't find a way to "wait" long enough for the secondary thread to end. >My stategy was to post a flag (now protected with mutex's) so that the >secondary thread could see the "die" indicator and shutdown in an orderly >fashion with "AfxEndThread". My new problem is that the seconday thread checks >for the presense of the flag at the top and bottom of a neverEnding for loop. >This allows the loop to finish it's critical tasks before ending. > >The strategy was for the primary (app) thread to set the flag, and sit in a >while loop until ::GetExitCodeThread showed that the secondary thread quit. >Initially, the primary while loop was running so fast, that the secondary >thread seemed never to get any cycles to do it's thing. I placed a Sleep in >the primary while loop, short at first, then as long as 5 seconds to wait for >the secondary thread to do it's thing. To my surprise, the Primary Sleep, >seems to put the secondary thread to sleep too. I have a status window, that >is updated by both threads. Up until the primary while loop (in the code >below) the secondary thread is updating the window reguarly. As soon as the >primary while loop (while Still_Active) starts, only the primary loop echo's a >status. This happens regardless of whether I Sleep 25ms or 5000ms. > >Does, Sleeping in the primary thread always put all secondary threads to sleep? >If so, how does one block or sleep a primary thread and still allow background >processes to go? > >Given my present delima, can anyone give me some advice regarding how to >shutdown a secondary thread, and be assured it is shutdown before continuing? >> >prmslick@infi.net >Using Pegasus Mail Win95 and OS2 Warp > > >From the SDK about Sleep: "Specifies the time, in milliseconds, for which to suspend execution. A value of zero causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run. If there are no other threads of equal priority ready to run, the function returns immediately, and the thread continues execution. A value of INFINITE causes an infinite delay." If the second thread have a lower priority you must use WaitForSingleObject with the thread's handle. When a thread (or Process) ends, its handle gets signaled. //------------------------------------------------------------// // Peter Olesen // // (peter.olesen@mailbox.swipnet.se) // // // // "Support the Blue Ribbon Campaign for free speech online." // //------------------------------------------------------------//
| Вернуться в корень Архива |