It's not a good idea (some would even say it's a horrible idea) to end threads in this manner.
Typically, the way to tell a thread to end is like so: a thread should be doing something, usually in a loop of some sort. Your loop should check for some signal from the main thread periodically and if set, end itself cleanly.
HANDLE m_hThreadExitEvent = NULL;
void CreateThreads(void)
{
CWinThread *pThread = NULL;
m_hThreadExitEvent = CreateHandle(NULL, TRUE, FALSE, NULL);
pThread = AfxBeginThread(ThreadFunc, NULL);
// Do some stuff.....
SetEvent(m_hThreadExitEvent);
DWORD dwRes = WaitForSingleObject(pThread->m_hThread, 2000); // Timeout is in milliseconds - if it doesn't complete in 2 seconds, we'll terminate it in an unclean fashion!
switch(dwRes)
{
case WAIT_OBJECT_0:
// It completed nicely!
break;
default:
// Could actually be WAIT_ABANDONED or WAIT_TIMEOUT
if(pThread)
{
// There's no clearup garauntee if you dynamically assign stuff in your thread
pThread->SuspendThread();
delete pThread;
}
}
}
UINT ThreadFunc(LPVOID pParam)
{
BOOL fDone = FALSE;
// Thread loop - you sometimes see this as for(;;) and it has a return in the middle of the loop
while(fDone == FALSE)
{
// I use this as a timer, it means the loop will run approx 1x per 100ms
DWORD dwRes = ::WaitForSingleObject(m_hThreadExitEvent, 100);
switch(dwRes)
{
case WAIT_OBJECT_0:
fDone = TRUE;
default:
// Thread specific stuff here
}
}
return 0;
}
Rather than use sleep, I use a wait event to give other threads a chance, if you wanted to run flat out, you could use a timeout of 0 and if the event is set, it will still work
Bear in mind, the programs starter is also a thread, I usually keep that MFC and use it as my user interface and have it driving everything else - the example here is a typical worker thread, additional user interface threads can also be created (but I don't bother, I've never needed more than 1 UI thread before)
Bookmarks