2009-02-26 21 views
10

Ho genera un thread utilizzando AfxBeginThread che è solo un infinito ciclo while:Come uccidere un thread MFC?

UINT CMyClass::ThreadProc(LPVOID param) 
{ 
    while (TRUE) 
    { 
     // do stuff 
    } 
    return 1; 
} 

Come faccio a uccidere questa discussione nella mia classe distruttore?

penso che qualcosa di simile

UINT CMyClass::ThreadProc(LPVOID param) 
{ 
    while (m_bKillThread) 
    { 
     // do stuff 
    } 
    return 1; 
} 

e quindi impostare m_bKillThread-FALSE nel distruttore. Ma ho ancora bisogno di aspettare nel distruttore fino a quando il filo è morto.

risposta

19

attivamente uccidendo il filo:

Utilizzare il valore restituito AfxBeginThread (CWinThread*) per ottenere la maniglia filo (m_hThread) allora passare l'impugnatura per l'API Win32 TerminateThread. Questo non è un modo sicuro per terminare i thread, quindi per favore continua a leggere.

Aspettando il filo alla fine:

Usa il valore di ritorno di AfxBeginThread (CWinThread*) per ottenere il membro m_hThread, quindi utilizzare WaitForSingleObject(p->m_hThread, INFINITE); Se questa funzione restituisce WAIT_OBJECT_0, poi il filo è finito. Invece di INFINITE puoi anche mettere il numero di millisecondi in attesa prima che si verifichi un timeout. In questo caso verrà restituito WAIT_TIMEOUT.

segnalazione al filo che dovrebbe finire:

Prima di fare il WaitForSingleObject basta impostare una sorta di bandiera che il filo deve uscire. Quindi nel tuo ciclo principale del thread verificherai quel valore bool e interromperesti il ​​ciclo infinito. Nel distruttore imposterai questa bandiera quindi esegui un WaitForSingleObject.

modi ancora meglio:

Se avete bisogno di un controllo ancora maggiore si può usare qualcosa di simile boost conditions.

1

È necessario attendere finché il thread non esegue tutte le operazioni.

if(WaitForSingleObject(thread_handle, INFINITE) == WAIT_OBJECT_0) 
    ;//all right 
else 
    ;//report error 

Attenzione con la funzione TerminateThread, questo è molto pericoloso.

4

BTW, Informazioni su TerminateThread(), utilizzare in questo modo.

DWORD exit_code= NULL; 
if (thread != NULL) 
{ 
    GetExitCodeThread(thread->m_hThread, &exit_code); 
    if(exit_code == STILL_ACTIVE) 
    { 
     ::TerminateThread(thread->m_hThread, 0); 
     CloseHandle(thread->m_hThread); 
    } 
    thread->m_hThread = NULL; 
    thread = NULL; 
} 
1

In primo luogo è necessario avviare la discussione in un modo così MFC non elimina l'oggetto thread quando è finished, l'impostazione predefinita per filo MFC è quello di eliminare se stesso in modo che si desidera spegnerlo.

m_thread = AfxBeginThread(ThreadProc, this, THREAD_PRIORITY_NORMAL ,CREATE_SUSPENDED); 
    m_thread->m_bAutoDelete = FALSE; 
    m_thread->ResumeThread(); 

Ora nel thread, si vuole un meccanismo che il thread chiamante può inviare un segnale per porre fine in sé. Ci sono diversi modi, uno è il WaitForSingleObject per controllare lo stato del segnale o un altro modo è semplicemente inviare questo thread un messaggio per terminare se stesso. Questo è un finale grazioso piuttosto che ucciderlo.

Mentre questo thread termina da solo (= uscita dalla funzione thread, pulizia), è possibile fare in modo che il thread principale lo attende per terminare prima di uscire.

 int wait = 2000 // seconds (I am waiting for 2 seconds for worker to finish) 
    int dwRes = WaitForSingleObject(m_thread->m_hThread, wait); 
    switch (dwRes) 
    { 
    case WAIT_OBJECT_0: 
     TRACE(_T("worker thread just finished")); break; 
    case WAIT_TIMEOUT: 
     TRACE(_T("timed out, worker thread is still busy")); break; 
    } 

impostazione Nota m_bAutoDelete = FALSE sopra reso possibile abbiamo ancora un handle valido quando il filo finisce in modo che possiamo aspettare su di esso. L'ultima cosa che vuoi fare ora è eliminare l'oggetto CWinThread per liberare la sua memoria (dato che ci siamo presi la responsabilità di farlo).