2012-06-27 41 views
6

我已经通过“CreateThread”函数创建了一个线程。Windows C++ - 用CloseHandle关闭线程

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

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

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

感谢

回答

8

CloseHandle()不会销毁,终止或supspend线程,它只会销毁句柄本身(因此您没有句柄来终止线程或等待它)。线程继续正常工作(我已经在很多情况下使用了它),停止它的唯一方法是退出线程函数(ThreadProc()),或者终止它。

6

一般来说,这(调用TerminateThread)是一个坏事情,因为一个线程可以分配一些资源(即文件描述符),这将无法使用,直到整个过程结束。更多的是,CloseHandle不会停止线程。

如果你有你的线程里面的一些冗长的操作,那么至少使用

while(!ShouldExit) 
{ 
    DoOneMoreIteration(); 
} 

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

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

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

例如,看到这个问题:Checking Win32 file streams for available input

它会像

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); 
+3

@ kakush,如果你去'ShouldExit',确保你声明它为'volatile'。否则,它可能无法做到这一点。 – eran

+0

@eran,你说得对。 –

+1

@eran:对于Visual C++编译器,'volatile'技巧只适用*。它可能不适用于其他编译器。 –

3

最好的事情是仔细阅读文档。 Win32 API有充分的文档记录。

MSDN on CreateThread in the Remarks section它说

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

接下来,你应该让线程入口函数完成它的工作并完成。即退出将返回线程入口函数的循环。