15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


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." //
//------------------------------------------------------------//





| Вернуться в корень Архива |