Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
623 views
in Technique[技术] by (71.8m points)

c - Terminating a thread gracefully not using TerminateThread()

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...