Click to See Complete Forum and Search --> : Cleaning up Threads


ejj
February 19th, 2003, 04:23 PM
I'm starting to design a C application that will have (at the moment) 5 threads (a UI thread, and 4 IO threads). 2 of these threads will be performing synchronous Serial IO, and 2 socket communication.

When the user clicks a 'Stop' button or closes the program, I need to clean up the threads that are running.

I've thought of a global variable to define the state of the application (when it becomes false, the threads will exit). However that could be a problem because some of them could be in the middle of a synchronous call (ReadFile for the serial port), and they couldn't exit until they timeout (which I haven't deterimed that time yet).

I could call TerminateThread, but I don't like that idea because if the thread is in a Critical Section that could screw things up, and if its blocked by an IO call, strange things could happen.

Any suggestions? What's a typical pratice in this situation?

mwilliamson
February 19th, 2003, 05:27 PM
Don't use terminate thread, your objects won't be cleaned up and you will leak memory. I don't think it has any pratical use.

An event is what I usually use. You should use routines that wait for a timeout before returning... If you can't for some reason, WSACleanUp() will force all socket routines to return.

Horst
February 20th, 2003, 02:44 AM
In my opinion, as you are using C - code, the easiest way would be to declare a global flag, and in every loop of your threads you check for it.

If the flag is reset you do the following steps in the thread procedure:

1) Close the thread handle (that will clean this up)

2) Set the handle to zero (thereby you can use this to verify thread closure)

3) Call "ExitThread" (This closes the thread and cleans thread overhead )

Thats it!

Hope this helped!

Horst

P. S. This of course works in C++ as well. But with classes you have to be more carefull e. g. threads are bit tricky to be included into a class

Andreas Masur
February 20th, 2003, 05:09 AM
Originally posted by Horst
1) Close the thread handle (that will clean this up)

2) Set the handle to zero (thereby you can use this to verify thread closure)

3) Call "ExitThread" (This closes the thread and cleans thread overhead )

You do not need steps one and two since this will be done automatically by 'ExitThread()'... :cool:

ejj
February 20th, 2003, 08:13 AM
All your suggestions make sense...however, how will the main (UI) thread know that all the others are exited? Because if I post a quit message, the message loop will terminate and the main thread will return which I assume (correct me if I'm wrong) terminate the other threads.

Some kind of singaling back to the main thread from the workers? There will be a fixed number of worker threads, so I could do this.

Thanks.

galathaea
February 20th, 2003, 02:38 PM
To know when the threads have finished, you can just WaitForMultipleObjects on all of the thread handles when main thread is done and ready to wait for them so it can exit. This would be after you signal them to finish up, of course.

Horst
February 21st, 2003, 02:17 AM
galathaea may be right in theory, but the problem is I've tried the approach with WaitForMultipleObjects and with me it failed altogether (Maybe it was my fault but I think it's just unreliable at application shutdown, in any other case the syncronisation objects of microsoft work pretty however).

The question I would consider is: Do you really need to know when all the threads are closed?

I thought so in some of my application first, but then I found out, that normally the threads are pretty able to clean after themselfes when programmed properly. And that's normally the reason behind knowing if it's gone.

If you truly need to know exactly when all the threads are ended, then I would suggest that you keep an array (etc.) of flags for the threads and the last step before a thread exits with ExitThread should be to set it's Flag False in that array. This means it has to be set to TRUE when you start it of course. Then you know for shure that this thread is gone.

In my experience this is the only truly shure method.

Hope this helped!

Horst

Andreas Masur
February 21st, 2003, 03:26 AM
Originally posted by Horst
The question I would consider is: Do you really need to know when all the threads are closed?

Well...while writing multithreaded applications one should preferrable always know the state of a specific thread (thread management). And you should of course make sure that you gracefully close every thread before exit from your application to ensure that all resource etc. get released. Otherwise you will run into memory and/or resource leaks...

hankdane
February 21st, 2003, 04:46 PM
Originally posted by Horst
I've tried the approach with WaitForMultipleObjects and with me it failed altogether Horst

Hmm... It has always worked for me. Then again, I don't like to use the Infinite flag for timeout -- I rather prefer a loop so that the thread with the WaitForMultipleObjects() has a chance to 'breathe' once in while, so to speak. Call me cynical, but whenever one statement contains both 'wait' and 'infinite', I get nervous.

Also, there are documented issues with having a message loop and WaitForMultipleObjects() in the same thread -- then you should use MsgWaitForMultipleObjects(). Maybe that was your problem?

davel
February 24th, 2003, 11:35 AM
What I do in my app is that I keep a count of number of worker threads. As each thread exits, it decrements the thread count (InterlockedDecrement). When the last thread exits, it posts a message to the UI thread indicating that all the threads have safely exited. The reason I dont want to use WaitForMultipleObjects in the UI thread is prevent it from being 'frozen'.
The above solution works fine for me (except when one of the worker threads which is doing I/O thru wininet is stuck in some wininet operation).

JamesSchumacher
February 25th, 2003, 12:21 AM
a semaphore?

davel
February 25th, 2003, 03:17 AM
Originally posted by JamesSchumacher
a semaphore?
can you elaborate as to how you would use a semaphore in this case (cleaning up worker threads and notifying UI thread)?

Andreas Masur
February 25th, 2003, 03:44 AM
The following uses two event semaphores to terminate the created thread...

class CFoo
{
public:
CFoo();
~CFoo();

private:
HANDLE m_hEventSemForStopThread;
HANDLE m_hEventSemForWaitThread;

static void ThreadFunction(void *pvParam);
};

CFoo::CFoo()
{
// Create event semaphore
HANDLE m_hEventSemForStopThread = CreateEvent(NULL, TRUE, FALSE, NULL);
HANDLE m_hEventSemForWaitThread = CreateEvent(NULL, TRUE, FALSE, NULL);

// Start thread
AfxBeginThread(ThreadFunction, this);
}

CFoo::~CFoo()
{
// Trigger thread to stop
::SetEvent(m_hEventSemForStopThread);

// Wait until thread finished
::WaitForSingleObject(m_hEventSemForWaitThread, INFINITE);

// Close handles
::CloseHandle(m_hEventSemForStopThread);
::CloseHandle(m_hEventSemForWaitThread);
}

void CFoo::ThreadFunction(void *vpParam)
{
CFoo *pParent = static_cast<CFoo *>(vpParam);

while(true)
{
// Check event sem for stop thread
if(::WaitForSingleObject(pParent->m_hEventSemStopThread, 0) == WAIT_OBJECT_0)
{
// Set event semaphore
::SetEvent(pParent->m_hEventSemWaitThread);

return;
}

// Do your processing
}
}

davel
February 25th, 2003, 12:17 PM
Andreas, You must be kidding me :)

A win32 semaphore is a kernel synchronization event created using 'CreateSemaphore'....all that you are doing is using normal win32 Events.

AFAIK a sempahore is used to control the number of users accessing a shared resource.

Andreas Masur
February 25th, 2003, 06:15 PM
Originally posted by davel
A win32 semaphore is a kernel synchronization event created using 'CreateSemaphore'....all that you are doing is using normal win32 Events.

AFAIK a sempahore is used to control the number of users accessing a shared resource.

Well...I might have used to word 'semaphore' in a widely manner here. It might have been clearer if I would have said 'object' instead... :cool: