2012-06-27 20 views
6

He creado un hilo mediante la función "CreateThread".Windows C++ - cierre del hilo con CloseHandle

en este hilo, tengo un ciclo 'while (true)' (que lee la entrada).

por ahora, cuando quiero cerrar el hilo, utilizo la función 'CloseHandle'.

¿Es esto lo correcto? ¿O debería salir del ciclo 'while (true)' y luego usar la función 'CloseHandle'?

Gracias

Respuesta

8

CloseHandle() no destruye, termina ni supedita el subproceso, solo destruye el identificador mismo (por lo tanto, no tiene un controlador para matar el subproceso o esperar en él). El hilo continúa funcionando normalmente (lo he utilizado en numerosos casos), y la única manera de detenerlo es salir de la función de hilo (ThreadProc()) o matarlo.

6

Generalmente esto (llamando TerminateThread) es una mala cosa que hacer porque un hilo puede asignar algunos recursos (es decir, los descriptores de archivos), que no estará disponible hasta terminar todo el proceso. Aún más, CloseHandle no detiene el hilo.

Si tiene alguna operación lenta dentro de su hilo, a continuación, al menos de la bicicleta de

while(!ShouldExit) 
{ 
    DoOneMoreIteration(); 
} 

. De esta forma puede terminar el hilo estableciendo ShouldExit en 1 (o 'verdadero', si es variable C++ y bool) y la llamada WaitForSingleObject en el identificador de este subproceso para asegurarse de que haya finalizado.

Para el comentario de los protagonistas: The ShouldExit debe declararse como 'volátil'.

Si está esperando alguna entrada (una consola, supongo), entonces puede usar la E/S no bloqueada ("superpuesta") con entrada estándar.

por ejemplo, véase la siguiente pregunta: Checking Win32 file streams for available input

Sería algo así como

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 
    } 
} 

Para hacer las cosas mejor (evitar overburn CPU) utiliza WaitForMultipleObjects y romper fuera del bucle en algún evento externo.

/// 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, si va por 'ShouldExit', asegúrese de declararlo como' volátil'.De lo contrario, podría no ser el truco. – eran

+0

@eran, tienes razón. –

+1

@eran: el truco 'volátil 'funciona * solo * para los compiladores de Visual C++. Es posible que no funcione en otros compiladores. –

3

Lo mejor es leer los documentos con cuidado. La API de Win32 está bien documentada.

de MSDN on CreateThread in the Remarks section Dice

ejecución del hilo comienza en la función especificada por el parámetro lpStartAddr . Si esta función retorna, el valor de retorno DWORD se usa para finalizar el hilo en una llamada implícita a la función ExitThread. Utilice la función GetExitCodeThread para obtener el valor de retorno del subproceso.

Después de eso, debe dejar que la función de entrada del hilo haga su trabajo y termine. Es decir. salir del bucle que devolvería la función de entrada de hilo.

Cuestiones relacionadas