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

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


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 Kumar 

The 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
        




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