I already solved the problem, but I hope that you have a better solution:
My app uses at least one worker thread. When started, it handles the communication via the rs232-comport.
When the user wants to close the whole app., I first tell the worker-thread to close. The last thing it does before leaving is to set a flag. My main program in the meantime just polls in a loop whether that flag is set. When found, it closes also.
So the worker thread sets the flag that it is closed already! I don't like my software to talk about future states of itself...
The code is working, but I think it is ineffective.
For the part where your main program waits for the worker thread to end, you can simplify it by using WaitForSingleObject(workerThreadHandle, INFINITE). It basically do the same thing for your except that you don't need to implement the loop.
Originally posted by Radu
The probably best way to close a thread is to use ExitThread(0) from within the thread. This way everything is cleaned up well. So, you can have something like:
Whoa! "Everything" is not cleaned up, and it is NOT the best way to close a thread...
Richter, "Programming Applications for Microsoft Windows":
You can force your thread to terminate by having it call ExitThread:
VOID ExitThread(DWORD dwExitCode);
This function terminates the thread and causes the operating system to clean up all of the operating system resources that were used by the thread. However, your C/C++ resources (such as C++ class objects) will not be destroyed. For this reason, it is much better to simply return from your thread function instead of calling ExitThread yourself.
The recommended way to have a thread terminate is by having its thread function simply return (as described in the previous section). However, if you use the method described in this section, be aware that the ExitThread function is the Windows function that kills a thread. If you are writing C/C++ code, you should never call ExitThread. Instead, you should use the Visual C++ run-time library function _endthreadex.
Note that calling ExitProcess or ExitThread causes a process or thread to die while inside a function. As far the operating system is concerned, this is fine and all of the process's or thread's operating system resources will be cleaned up perfectly. However, a C/C++ application should avoid calling these functions because the C/C++ run time might not be able to clean up properly
Making explicit calls to ExitProcess and ExitThread is a common problem that causes an application to not clean itself up properly. In the case of ExitThread, the process continues to run but can leak memory or other resources.
Thought for the day/week/month/year: Windows System Error 4006:
Replication with a nonconfigured partner is not allowed.
As this thread here became larger than expected, I just want to clarify:
The question was perfectly answered by the hint "WaitForSingleObject". I didn't have a problem in terminating the thread, the only problem I had was that I used an unlogical way to figure out when the thread really stopped. As I'm doing a worker-thread for serial communication, there are neither GUI-objects used nor are there really objects at all.
In the GUI thread, set a flag to tell worker threads they should end themselves at their own earliest possible convenience.
What you do next in the gui thread depends....
1) If the GUI thread doesn't need any results from the worker threads, just let the GUI thread end normally, while the worker threads are still running/shutting down. The process/application will properly terminate when all of it's threads are closed.
Note that the user will still see the process active in the taskmanager for some time after he/she has closed the 'application window'. This rarely is an issue anyway.
2) If the GUI thread must wait for worker threads to finish because it needs to save obtained data or thread progressstatus, needs to do cleanup which can't happen until all threads are closed, you will need to wait for the threads to finish.
The seemingly obvious (and easy) way to wait for a thread to finish is to use WaitForSingleObject(), but there are a couple catches to this...
- your program will be unresponsive while it's waiting, which can be a problem if the wait can take a long time.
- It's somewhat less suited if you have multiple worker threads. Although it's not necessarily bad doing it this way. At the least, you'll be sure the threads have ended, even though the thread you decided to wait on first, may end up being the one that finished last.
If ending a thread can take a long time, or if you have multiple threads, then I have (and this has worked nicely so far) used the following system...
When creating a thread, a counter gets incremended, this counter will always contain the number of active threads (excluding the GUI thread). Use InterlockedIncrement().
When the GUI wants to end, it sets a 'threads_end_yourself' flag. When this flag is set, all (harmfull) menu-items are disabled.
Threads check this flag in their working loop, and shut themselves down at their own earliest possible convenience.
At thread end, the thread decrements the flag, and when it hits zero, it posts a user-message telling the GUI all threads are now closed. Each workerthread ends with the code:
Or if you use MFC, you can create your own overridden CWinThread, and stuff that code in ExitThread().
When the GUI receives the WM_ALL_THREADS_ENDED, it does it's cleanup, and terminates.
It's easy enough to display a "shutting down, please wait" type dialog using this method.
While it may take a little more work this way. It does provide a clean, safe way to end your app that will work in all cases, provided you follow the three rules below.
- It won't use ANY significant CPU time, which any form of polling loop (nomatter how smart you can make it) WILL.
- Your app stays responsive (user can move/size window, there's a proper message telling the app is busy...) while it's shutting down.
3 rules if you want reliable multithreading code...
1) Don't use ExitThread()
2) If think you need to use ExitThread(), then reread rule 1.
3) If you think you have found a legitimate use of ExitThread(), then reread rule 1.