Multithreading: terminazione dei thread in MFC

Due situazioni normali causano l'interruzione di un thread: la funzione di controllo esce o il thread non può essere eseguito fino al completamento. Se un elaboratore di testo usava un thread per la stampa in background, la funzione di controllo termina normalmente se la stampa è stata completata correttamente. Se l'utente desidera annullare la stampa, tuttavia, il thread di stampa in background deve essere terminato prematuramente. Questo argomento illustra sia come implementare ogni situazione che come ottenere il codice di uscita di un thread dopo il termine.

Terminazione normale del thread

Per un thread di lavoro, la terminazione normale del thread è semplice: uscire dalla funzione di controllo e restituire un valore che indica il motivo della terminazione. È possibile usare la funzione AfxEndThread o un'istruzione return . In genere, 0 indica il completamento corretto, ma questo è per te.

Per un thread dell'interfaccia utente, il processo è semplice: dall'interno del thread dell'interfaccia utente chiamare PostQuitMessage in Windows SDK. L'unico parametro che PostQuitMessage accetta è il codice di uscita del thread. Come per i thread di lavoro, 0 in genere indica il completamento riuscito.

Terminazione del thread prematura

Terminare un thread in modo prematuro è quasi semplice: chiamare AfxEndThread dall'interno del thread. Passare il codice di uscita desiderato come unico parametro. Questo arresta l'esecuzione del thread, dealloca lo stack del thread, scollega tutte le DLL collegate al thread ed elimina l'oggetto thread dalla memoria.

AfxEndThread deve essere chiamato dall'interno del thread da terminare. Se si vuole terminare un thread da un altro thread, è necessario configurare un metodo di comunicazione tra i due thread.

Recupero del codice di uscita di un thread

Per ottenere il codice di uscita del thread di lavoro o dell'interfaccia utente, chiamare la funzione GetExitCodeThread . Per informazioni su questa funzione, vedere Windows SDK. Questa funzione accetta l'handle per il thread (archiviato nel m_hThread membro dati degli CWinThread oggetti) e l'indirizzo di un DWORD.

Se il thread è ancora attivo, GetExitCodeThread inserisce STILL_ACTIVE nell'indirizzo DWORD fornito; in caso contrario, il codice di uscita viene inserito in questo indirizzo.

Il recupero del codice di uscita degli oggetti CWinThread richiede un passaggio aggiuntivo. Per impostazione predefinita, quando un CWinThread thread termina, l'oggetto thread viene eliminato. Ciò significa che non è possibile accedere al m_hThread membro dati perché l'oggetto CWinThread non esiste più. Per evitare questa situazione, eseguire una delle operazioni seguenti:

  • Impostare il m_bAutoDelete membro dati su FALSE. Ciò consente all'oggetto CWinThread di sopravvivere dopo che il thread è stato terminato. È quindi possibile accedere al m_hThread membro dati dopo che il thread è stato terminato. Se si usa questa tecnica, tuttavia, si è responsabili dell'eliminazione dell'oggetto CWinThread perché il framework non lo eliminerà automaticamente. Questo è il metodo preferito.

  • Archiviare separatamente l'handle del thread. Dopo aver creato il thread, copiare m_hThread il membro dati (usando ::DuplicateHandle) in un'altra variabile e accedervi tramite tale variabile. In questo modo l'oggetto viene eliminato automaticamente quando si verifica la terminazione ed è comunque possibile scoprire perché il thread è terminato. Prestare attenzione che il thread non venga terminato prima di poter duplicare l'handle. Il modo più sicuro per eseguire questa operazione consiste nel passare CREATE_SUSPENDED ad AfxBeginThread, archiviare l'handle e quindi riprendere il thread chiamando ResumeThread.

Entrambi i metodi consentono di determinare il motivo per cui un CWinThread oggetto è terminato.

Vedi anche

Multithreading con C++ e MFC
_endthread, _endthreadex
_beginthread, _beginthreadex
ExitThread