Click to See Complete Forum and Search --> : Thread termination problem.
CCC
November 23rd, 2004, 03:48 AM
Hi
I started a thread to check for a file change using the below code
CWinThread* m_UpdateMonitorThread = AfxBeginThread(CheckFileUpdates,(LPVOID)this)
UINT CheckFileUpdates(LPVOID lp)
{
while( ReadDirectoryChangesW(
hDir, // handle to directory
&Buffer, // read results buffer
sizeof(Buffer), // length of buffer
TRUE, // monitoring option
FILE_NOTIFY_CHANGE_SIZE, // filter conditions
&BytesReturned, // bytes returned
NULL, // overlapped buffer
NULL// completion routine
))
{
//do the work
}
}
Now on I have abutton on my UI. Onclick of the button I want to stop the above thread.
I I tried to use
if(m_UpdateMonitorThread)
{
DWORD dwRetCode;
while (!GetExitCodeThread(m_UpdateMonitorThread->m_hThread, &dwRetCode));
TerminateThread(m_UpdateMonitorThread->m_hThread,dwRetCode);
m_UpdateMonitorThread = NULL;
}
and
if(m_UpdateMonitorThread)
{
m_UpdateMonitorThread->SuspendThread();
m_UpdateMonitorThread->Delete();
m_UpdateMonitorThread = NULL;
}
I am getting memory leaks in both the above cases. I tried to post a Stop Event, but where do I wait for this event inside the thread code as execution will not go inside the while loop code because of ReadDirectoryChangesW.
Can anyone please please suggest a way out to this problem.
Thanks in anticipation of information.
Madhavi
Andreas Masur
November 23rd, 2004, 05:42 AM
Take a look at the following FAQ (http://www.codeguru.com/forum/showthread.php?t=305166)...
kuphryn
November 23rd, 2004, 11:57 AM
One solution is a boolean status variable.
Kuphryn
NigelQ
November 24th, 2004, 01:12 AM
You could certainly use kuphryn's approach by using a flag variable to signal a shutdown from outside the thread.
You could also try:
if(m_UpdateMonitorThread)
{
m_UpdateMonitorThread.PostThreadMessage(WM_QUIT, 0L, 0L);
}
This will cause the thread to shutdown due to the fact that it has a message queue and should see the incoming WM_QUIT message (assuming it's not tied up somewhere not processing messages).
There are two problems with this approach, one of which is also associated with kyphryn's, namely waiting for the thread to be shutdown before continuing.
The safest way to shutdown a thread is to make sure it actually stopped after being signalled to do so. By setting a flag or posting a message to the worker thread, you are merely hoping and assuming it shuts down correctly (and indeed it might), however if there are problems with the thread shutting down, you can start having interesting problems.
The second problem is to do with posting a WM_QUIT message to the thread as you have created it; with the m_bAutoDelete flag set. This means the thread object will be destroyed as soon as the thread terminates, meaning that it is difficult to then determine that it has in fact stopped.
This leads to a problem in my earlier PostThreadMessage code. If the thread had already terminated itself (for whatever reason), the m_UpdateMonitorThread value would not be NULL (why should it be), therefore an attempt to send the WM_QUIT message would be made to the (invalid) thread handle. This is bad.
You can get around this by creating the thread as suspended, then clear the auto delete flag, then use the thread handle itself to determine when the thread has actually terminated.
Wow this is getting complicated!!
The following should work nicely:
To create the thread:
CWinThread* m_UpdateMonitorThread = AfxBeginThread(CheckFileUpdates,(LPVOID)this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED, NULL);
m_UpdateMonitorThread.m_bAutoDelete = false;
m_UpdateMonitorThread.ResumeThread();
// The thread is running and will not delete itself when done
Now to stop it...
if(m_UpdateMonitorThread)
{
// we should not get an exception here because the thread object will only be destroyed here
m_UpdateMonitorThread.PostThreadMessage(WM_QUIT, 0L, 0L);
// Now, wait for the thread to terminate itself (for a couple of seconds)
if(WaitForSingleObject(m_UpdateMonitorThread.m_hThread, 2000) == WAIT_TIMEOUT)
{
// The thread doesn't seem to want to close itself, let's force it (this should be a last ditch thing to do)
TerminateThread(m_UpdateMonitorThread.m_hThread, 1);
}
// Now destroy the thread object (it should be stopped by now)
delete m_UpdateMonitorThread;
m_UpdateMonitorThread = NULL; // just in case you get tempted to send it more messages :-)
}
Hope this helps,
- Nigel
kuphryn
November 24th, 2004, 01:46 AM
Another solution is to pass in a pointer to a boolean variable.
Kuphryn
Andreas Masur
November 24th, 2004, 03:12 AM
This will cause the thread to shutdown due to the fact that it has a message queue and should see the incoming WM_QUIT message (assuming it's not tied up somewhere not processing messages).
Well...where do you see a message queue in the thread?
NigelQ
November 24th, 2004, 12:46 PM
Ah Andreas - you're correct. I was half asleep obviously.
Sorry for the confusion.
- Nigel
Andreas Masur
November 24th, 2004, 04:16 PM
Ah Andreas - you're correct. I was half asleep obviously.
*lol*...no problem...at the time I read your post I was still running without any coffee myself...so I might have missed the queue as well... :eek:
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.