2016-05-05 32 views
5

ho qualcosa di simile:Come con grazia arresto un filo in C

DWORD WINAPI test(LPVOID lpParam) { 
    while (1) { 
     /*DO STUFF*/ 
    } 
} 

int main() { 
    ... 
    hThread = CreateThread(NULL,0,test,NULL,0,&dwThreadId); 
    ... 
} 

Come posso spegnere il filo, senza TerminateThread()? La mia prima idea è stata la creazione di una variabile globale (shouldshutdown = 0/1), impostarla nel main() quando il Thread dovrebbe chiudersi. Quindi chiama ExitThread() nella discussione. Quindi devo controllare questa variabile nel ciclo while del thread che è uno stile cattivo, credo.

+0

Come saprà il thread deve restituire? – 2501

+0

utilizza gestori di segnale – Charlestone

+0

@ 2501 Non funziona. Questo è il problema. Devo implementare qualcosa come un controllo nel ciclo: voglio evitare questo. – Kntlii

risposta

11

È un evento che il thread può controllare per vedere se è necessario fermarsi. Ad esempio (senza gestione degli errori):

DWORD WINAPI test(LPVOID lpParam) 
{ 
    HANDLE hEvent = (HANDLE)lpParam 

    while (WaitForSingleObject(hEvent, 0) == WAIT_TIMEOUT) 
    { 
     /*DO STUFF*/ 
    } 
} 

int main() { 
    hEvent = CreateEvent(NULL, TRUE, FALSE, NULL) 
    hThread = CreateThread(NULL,0,test,(LPVOID)hEvent,0,&dwThreadId); 
    // Do 
    // Stuff 
    // Tell the thread to exit 
    SetEvent(hEvent) 

    // Wait for the thread to exit 
    WaitForSingleObject(hThread, INFINITE); 
} 

Lo schema generale è quello di dare il filo qualche oggetto alertable che può controllare e qualcos'altro può impostare. In questo caso ho usato un evento di reset manuale. Il ciclo while controlla se l'evento è stato segnalato e, in caso contrario, lo fa. Quando viene segnalato, WaitForSingleObject restituirà WAIT_OBJECT_0 e il ciclo uscirà e cadrai fuori dalla funzione thread.

Nella funzione principale tutto ciò che è necessario fare dopo aver segnalato l'evento è attendere che il thread esca.

+0

Non funziona se il thread è associato alla CPU in alcune librerie opache. –

+1

@MartinJames, ma in questo caso non si ha molto da fare in questo caso. –

+0

Sarebbe molto più efficiente utilizzare le [funzioni di accesso variabile interbloccate] (https://msdn.microsoft.com/en-us /library/windows/desktop/ms684122(v=vs.85).aspx) rispetto a un oggetto evento. –

0

Se è necessario inviare messaggi tra il thread principale e i thread di lavoro, ad esempio il lavoro da eseguire è costituito da attività che vengono posizionate su una coda, l'opzione più semplice potrebbe essere semplicemente fornire al thread worker un messaggio ciclo continuo.

L'API PostThreadMessage può essere utilizzata per inviare i messaggi WM_APP alla discussione con attività da eseguire e un messaggio WM_QUIT quando il thread deve uscire. Ciò ti consente di creare meccanismi di segnalazione sicuri per i thread.

Ha il vantaggio collaterale che, se il thread di lavoro crea un'istanza di oggetti COM, tutto ciò che è necessario fare è aggiungere una chiamata iniziale a CoInitialize e il thread è un STA valido.

+0

Qualsiasi thread che usi COM ** deve ** chiamare 'CoInitialize/Ex()' comunque. Ma un thread non ha bisogno di usare COM per creare un loop di messaggi per se stesso. –

+0

@RemyLebeau corretto. Grazie. –

0

Se si desidera arrestare una discussione, sono disponibili due opzioni: 1. Forzare il thread per terminare (con TerminateThread). 2. Chiedere al thread di spegnersi (per far funzionare questo thread deve cooperare).

Se si sceglie la seconda opzione, è possibile scegliere come eseguire l'operazione. Una scelta è quella di usare una bandiera globale per dire al thread di terminare (non sono sicuro del motivo per cui pensi che sia cattivo stile). La scelta migliore dipenderà probabilmente da cosa sta facendo il tuo thread.