2012-06-27 12 views
6

Ho creato un thread con la funzione "CreateThread".Windows C++ - thread di chiusura con CloseHandle

in questo thread, ho un ciclo while (true) '(che legge l'input).

per ora, quando voglio chiudere il thread, utilizzo la funzione 'ChiudiChiave'.

È questa la cosa giusta da fare? O dovrei uscire dal ciclo 'while (true)' e quindi usare la funzione 'CloseHandle'?

Grazie

risposta

8

CloseHandle() non distrugge, termina o sovrascrive il thread, ma distrugge solo l'handle stesso (quindi non si dispone di un handle per chiudere il thread o attendere su di esso). Il thread continua a funzionare normalmente (l'ho utilizzato in numerosi casi) e l'unico modo per fermarlo è uscire dalla funzione thread (ThreadProc()) o ucciderlo.

6

Generalmente questo (chiamando TerminateThread) è una cattiva cosa da fare perché un thread può allocare alcune risorse (cioè, descrittori di file), che non sarà disponibile fino a quando l'intero processo termina. Inoltre, CloseHandle non interrompe il thread.

Se avete un po 'lunga operazione all'interno del filo, poi almeno usare il ciclo

while(!ShouldExit) 
{ 
    DoOneMoreIteration(); 
} 

. In questo modo è possibile interrompere il thread impostando ShouldExit su 1 (o 'true', se è C++ e variabile bool) e chiama WaitForSingleObject sull'handle di questo thread per assicurarsi che sia terminato.

Per il commento di eran: L'espressione ShouldExit deve essere dichiarata come "volatile".

Se si sta aspettando un input (suppongo una console), è possibile utilizzare l'I/O non bloccato ("sovrapposto") con input standard.

esempio vedi questa domanda: Checking Win32 file streams for available input

Sarebbe qualcosa di simile

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

Per rendere le cose migliori (evitare overburn CPU) utilizzare WaitForMultipleObjects e rompere fuori del ciclo su qualche evento esterno.

/// 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, se si utilizza "ShouldExit', assicurarsi di dichiararlo come" volatile ".Altrimenti, potrebbe non funzionare. – eran

+0

@eran, hai ragione. –

+1

@eran: Il trucco 'volatile' funziona * solo * per i compilatori di Visual C++. Potrebbe non funzionare su altri compilatori. –

3

La cosa migliore è leggere attentamente i documenti. L'API Win32 è ben documentata.

da MSDN on CreateThread in the Remarks section si dice

esecuzione Discussione inizia la funzione specificata dal parametro lpStartAddr . Se questa funzione viene restituita, il valore di ritorno DWORD viene utilizzato per e termina il thread in una chiamata implicita alla funzione ExitThread. Utilizzare la funzione GetExitCodeThread per ottenere il valore di ritorno del thread.

In seguito, è necessario lasciare che la funzione di inserimento dei thread faccia il suo lavoro e termini. Cioè uscire dal ciclo che restituirebbe la funzione di inserimento del thread.

Problemi correlati