Windows – Terminating a thread gracefully not using TerminateThread()

c++, multithreading, windows

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.

Best Solution

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.