My application creates a thread and that runs in the background all the time. I can only terminate the thread manually, not from within the thread callback function.
At the moment I am using TerminateThread()
to kill that thread but it's causing it to hang sometimes.
I know there is a way to use events and WaitForSingleObject()
to make the thread terminate gracefully but I can't find an example about that.
Please, code is needed here.
A thread automatically terminates when it returns from its entry-point routine. A thread can also explicitly terminate itself or terminate any other thread in the process, using a mechanism called cancelation.
To create a thread, either we declare a variable of that thread class or use new to actually create one. After this, the thread is created. To run it, we have to call the method ThreadFunc() of that thread. When the execution of a thread reaches a return point or executes the call to Exit(), it terminates.
Once ExitProcess() is called, the OS will stop ALL threads of the process, no matter what state they are in, before deallocating any memory, (like the memory containing your flag). The thread that calls ExitProcess() never has control returned to it.
TerminateThread is a bad idea, especially if your thread uses synchronization objects such as mutexes. It can lead to unreleased memory and handles, and to deadlocks, so you're correct that you need to do something else.
Typically, the way that a thread terminates is to return from the function that defines the thread. The main thread signals the worker thread to exit using an event object or a even a simple boolean if it's checked often enough. If the worker thread waits with WaitForSingleObject
, you may need to change it to a WaitForMultipleObjects
, where one of the objects is an event. The main thread would call SetEvent
and the worker thread would wake up and return.
We really can't provide any useful code unless you show us what you're doing. Depending on what the worker thread is doing and how your main thread is communicating information to it, it could look very different.
Also, under [now very old] MSVC, you need to use _beginthreadex
instead of CreateThread
in order to avoid memory leaks in the CRT. See MSKB #104641.
Update:
One use of worker thread is as a "timer", to do some operation on regular intervals. At the most trivial:
for (;;) {
switch (WaitForSingleObject(kill_event, timeout)) {
case WAIT_TIMEOUT: /*do timer action*/ break;
default: return 0; /* exit the thread */
}
}
Another use is to do something on-demand. Basically the same, but with the timeout set to INFINITE
and doing some action on WAIT_OBJECT_0
instead of WAIT_TIMEOUT
. In this case you would need two events, one to make the thread wake up and do some action, another to make it wake up and quit:
HANDLE handles[2] = { action_handle, quit_handle };
for (;;) {
switch (WaitForMultipleObject(handles, 2, FALSE, INFINITE)) {
case WAIT_OBJECT_0 + 0: /* do action */ break;
default:
case WAIT_OBJECT_0 + 1: /* quit */ break;
}
}
Note that it's important that the loop do something reasonable if WFSO/WFMO return an error instead of one of the expected results. In both examples above, we simply treat an error as if we had been signaled to quit.
You could achieve the same result with the first example by closing the event handle from the main thread, causing the worker thread get an error from WaitForSingleObject
and quit, but I wouldn't recommend that approach.
Since you don't know what the thread is doing, there is no way to safely terminate the thread from outside.
Why do you think you cannot terminate it from within?
You can create an event prior to starting the thread and pass that event's handle to the thread. You call SetEvent()
on that event from the main thread to signal the thread to stop and then WaitForSingleObject
on the thread handle to wait for the thread to actually have finished. Within the threads loop, you call WaitForSingleObject()
on the event, specifying a timeout of 0
(zero), so that the call returns immediately even if the event is not set. If that call returns WAIT_TIMEOUT
, the event is not set, if it returns WAIT_OBJECT_0
, it is set. In the latter case you return from the thread function.
I presume your thread isn't just burning CPU cycles in an endless loop, but does some waiting, maybe through calling Sleep()
. If so, you can do the sleeping in WaitForSingleObject
instead, by passing a timeout to it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With