13

我通过“CreateThread”函数创建了一个线程。

在这个线程中,我有一个“while(true)”循环(读取输入)。

现在,当我想关闭线程时,我使用“CloseHandle”函数。

这是正确的做法吗?或者我应该退出 'while(true)' 循环,然后使用 'CloseHandle' 函数?

谢谢

4

3 回答 3

19

CloseHandle() 不会破坏、终止或暂停线程,它只会破坏句柄本身(因此您没有句柄来杀死线程或等待它)。线程继续正常工作(我在很多情况下都使用过它),停止它的唯一方法是退出线程函数(ThreadProc()),或者杀死它。

于 2012-06-27T12:44:46.593 回答
6

一般来说,这(调用 TerminateThread)是一件坏事,因为线程可能会分配一些资源(即文件描述符),这些资源在整个进程终止之前将不可用。更重要的是,CloseHandle 不会停止线程。

如果您的线程中有一些冗长的操作,那么至少使用

while(!ShouldExit)
{
     DoOneMoreIteration();
}

循环。这样,您可以通过将 ShouldExit 设置为 1(或“true”,如果它是 C++ 和 bool 变量)并在此线程的句柄上调用 WaitForSingleObject 来终止线程,以确保它已完成。

对于eran 的评论:ShouldExit 必须声明为'volatile'。

如果您正在等待某些输入(我想是一个控制台),那么您可以将非阻塞(“重叠”)I/O 与标准输入一起使用。

例如,请参阅以下问题:检查 Win32 文件流以获取可用输入

会是这样的

HANDLE h = GetStdHandle(STD_INPUT_HANDLE);

while(!ShouldExit) {
   if(WaitForSingleObject(h, FALSE, SomeTimeoutValue) == WAIT_OBJECT_0)
   {
      ... use std::cin - it has some input and won't block
   }
}

为了让事情变得更好(避免 CPU 过载),请使用 WaitForMultipleObjects 并在某些外部事件上中断循环。

/// Global var
HANDLE SomeGlobalEvent;

/// ThreadProc():
HANDLE h[2];
h[0] = GetStdHandle(STD_INPUT_HANDLE);
h[1] = SomeGlobalEvent;

while(true) {
   DWORD which = WaitForMultipleObjects(2, h, FALSE, SomeTimeoutValue);
   if(which == WAIT_OBJECT_0)
   {
      ... use std::cin - it has some input and won't block
   } else
   if(which == WAIT_OBJECT_1)
   {
      // got the termination event
      break;
   }
}


/// "Main" thread:

SomeGlobalEvent = CreateEvent(NULL, false, false, NULL);

HANDLE hThread = _beginthread(ThreadProc, 4096, NULL);

 ....
 /// send termination signal
 SetEvent(SomeGlobalEvent);

 /// Wait for thread completion
 WaitForSingleObject(hThread);
于 2012-06-27T12:24:42.917 回答
3

最好的办法是仔细阅读文档。Win32 API 有据可查。

来自MSDN on CreateThread 在备注部分它说

线程执行从 lpStartAddr 参数指定的函数开始。如果此函数返回,则 DWORD 返回值用于在对 ExitThread 函数的隐式调用中终止线程。使用 GetExitCodeThread 函数获取线程的返回值。

从那以后,你应该让线程入口函数完成它的工作并完成。即退出将返回线程入口函数的循环。

于 2012-06-27T12:24:50.370 回答