2009-02-26 11 views
10

ich Laichen einen Thread AfxBeginThread verwendet, die nur eine unendliche while-Schleife ist:Wie töte ich einen MFC-Thread?

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

Wie abzutöten ich diesen Thread in meiner Klasse destructor?

Ich denke, so etwas wie

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

und dann m_bKillThread-FALSE im destructor gesetzt. Aber ich muss immer noch im Destruktor warten, bis der Thread tot ist.

Antwort

19

Aktiv den Faden Tötung:

Verwenden Sie den Rückgabewert von AfxBeginThread (CWinThread*) den Faden Griff (m_hThread) dann, dass auf die TerminateThread Win32 API Handle übergeben zu bekommen. Dies ist jedoch kein sicherer Weg, um Threads zu beenden, also lesen Sie bitte weiter.

Warten auf den Thread zu beenden:

Verwenden Sie den Rückgabewert von AfxBeginThread (CWinThread*) das Mitglied m_hThread zu bekommen, dann WaitForSingleObject(p->m_hThread, INFINITE); verwenden Wenn diese Funktion WAIT_OBJECT_0 zurückgibt, dann wird der Thread beendet ist. Anstelle von INFINITE können Sie auch die Anzahl der Millisekunden angeben, die gewartet werden soll, bis ein Timeout eintritt. In diesem Fall wird WAIT_TIMEOUT zurückgegeben.

Signalisierung zu Thread, dass es enden soll:

Zuvor die WaitForSingleObject nur eine Art von Flag gesetzt, dass der Faden verlassen sollte. Dann würden Sie in Ihrer Hauptschleife des Threads nach diesem Bool-Wert suchen und die Endlosschleife aufbrechen. In Ihrem Destruktor würden Sie diese Flagge setzen und dann eine WaitForSingleObject tun.

Noch bessere Möglichkeiten:

Wenn Sie noch mehr Kontrolle benötigen Sie so etwas wie boost conditions verwenden können.

1

Sie müssen warten, bis Thread alle Sachen erledigen.

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

Vorsicht mit TerminateThread-Funktion, das ist sehr gefährlich.

4

BTW, Über TerminateThread(), verwenden Sie es auf diese Weise.

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

Zuerst Sie den Faden in einer Art und Weise zu beginnen haben so MFC nicht das Objekt Thread löschen, wenn es finished ist, ist die Standardeinstellung für MFC Thread selbst zu löschen, so dass Sie das ausschalten möchten.

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

Jetzt im Thread, wollen Sie einen Mechanismus, dass der Anrufer Thread kann ein Signal senden, um sich zu beenden. Es gibt mehrere Möglichkeiten, eine ist die WaitForSingleObject, um den Status des Signals zu überprüfen oder eine andere Möglichkeit besteht darin, einfach diesem Thread eine Nachricht zu senden, um sich selbst zu beenden. Das ist ein anmutiges Ende, das eher tötet.

Während dieser Thread sich selbst beendet (= Beenden der Thread-Funktion, Bereinigen), können Sie den Haupt-Thread darauf warten, dass er beendet wird, bevor er beendet wird.

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

Hinweis Einstellung m_bAutoDelete = FALSE oben machte es möglich, dass wir noch einen gültigen Griff haben, wenn Thread beendet, so dass wir auf sie warten. Das letzte, was Sie jetzt tun möchten, ist das CWinThread-Objekt zu löschen, um seinen Speicher freizugeben (da wir die Verantwortung dafür übernommen haben).

Verwandte Themen