我的应用程序创建了一个线程,该线程一直在后台运行。我只能手动终止线程,而不能从线程回调函数内部终止。
目前,我正在使用TerminateThread()
杀死该线程,但有时会导致其挂起。
我知道有一种使用事件和WaitForSingleObject()
的方法可以使线程正常终止,但是我找不到关于此的示例。
请在这里需要代码。
最佳答案
TerminateThread是个坏主意,尤其是在您的线程使用同步对象(例如互斥体)的情况下。它可能导致未释放的内存和句柄以及死锁,因此您正确地需要做其他事情。
通常,线程终止的方式是从定义线程的函数返回。如果经常检查主线程,则使用事件对象或什至是简单的 bool 值来通知工作线程退出。如果辅助线程等待WaitForSingleObject
,则可能需要将其更改为WaitForMultipleObjects
,其中对象之一是事件。主线程将调用SetEvent
,而工作线程将唤醒并返回。
除非您向我们展示您的工作,否则我们真的无法提供任何有用的代码。根据工作线程在做什么以及您的主线程如何向其传达信息,它看起来可能会大不相同。
同样,在[非常老的] MSVC下,您需要使用_beginthreadex
而不是CreateThread
以避免CRT中的内存泄漏。参见MSKB #104641。
更新:
辅助线程的一种用法是用作“计时器”,以定期执行一些操作。最琐碎的是:
for (;;) {
switch (WaitForSingleObject(kill_event, timeout)) {
case WAIT_TIMEOUT: /*do timer action*/ break;
default: return 0; /* exit the thread */
}
}
另一个用途是按需执行某些操作。基本相同,但超时设置为
INFINITE
,并对WAIT_OBJECT_0
而不是WAIT_TIMEOUT
进行了一些操作。在这种情况下,您将需要两个事件,一个使线程唤醒并执行某些操作,另一个使它唤醒并退出: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;
}
}
请注意,如果WFSO/WFMO返回错误而不是预期结果之一,则循环必须执行合理的操作,这一点很重要。在以上两个示例中,我们仅将错误视为已被告知要退出。
通过关闭主线程的事件句柄,导致工作线程从
WaitForSingleObject
中获取错误并退出,您可以在第一个示例中获得相同的结果,但是我不推荐这种方法。