Multithreading: Beenden von Threads in MFC
In den beiden folgenden Fällen wird die Beendigung eines Threads ordnungsgemäß ausgelöst: die Steuerungsfunktion wird beendet, oder der Thread darf nicht vollständig ausgeführt werden. Falls z. B. in einem Textverarbeitungsprogramm ein Thread für den Hintergrunddruck verwendet wird, wird die Steuerungsfunktion normal beendet, sobald der Druckauftrag erfolgreich abgeschlossen ist. Wenn der Benutzer den Druckvorgang jedoch abbrechen möchte, muss der Thread für den Hintergrunddruck vorzeitig beendet werden. In diesem Thema wird beschrieben, wie jede Situation zu implementieren ist und wie der Exitcode des Threads nach seiner Beendigung ermittelt wird.
Normale Threadbeendigung
Von einem Arbeitsthread werden bei der normalen Threadbeendigung folgende einfache Schritte ausgeführt: die Steuerungsfunktion wird beendet und es wird ein Wert zurückgegeben, aus dem der Grund für die Beendung hervorgeht. Sie können entweder die AfxEndThread-Funktion oder eine return
Anweisung verwenden. Normalerweise steht null0null für die erfolgreiche Ausführung; dies ist ganz Ihnen überlassen.
Bei einem Benutzeroberflächenthread ist der Prozess genauso einfach: Rufen Sie postQuitMessage im Windows SDK aus dem Benutzeroberflächenthread auf. Der einzige Parameter, PostQuitMessage
der den Exitcode des Threads annimmt. Bei Arbeitsthreads steht null0null normalerweise für eine erfolgreiche Ausführung.
Vorzeitige Threadendung
Das vorzeitige Beenden eines Threads ist fast so einfach: Rufen Sie AfxEndThread aus dem Thread auf. Übergeben Sie den gewünschten Exitcode als einzigen Parameter. Hierdurch wird die Ausführung des Threads beendet, der Stapel des Threads freigegeben, alle mit dem Thread verbundenen DLLs getrennt und das Threadobjekt aus dem Speicher gelöscht.
AfxEndThread
muss von dem zu beendenden Thread aus aufgerufen werden. Wenn Sie einen Thread von einem anderen Thread aus beenden möchten, müssen Sie ein Kommunikationsverfahren zwischen den beiden Threads einrichten.
Abrufen des Exit-Codes eines Threads
Rufen Sie die GetExitCodeThread-Funktion auf , um den Beendigungscode des Arbeits- oder Benutzeroberflächenthread-Threads abzurufen. Informationen zu dieser Funktion finden Sie im Windows SDK. Diese Funktion übernimmt das Handle für den Thread (gespeichert im m_hThread
Datenmememm der CWinThread
Objekte) und die Adresse eines DWORD.
Wenn der Thread noch aktiv ist, GetExitCodeThread
wird STILL_ACTIVE in der angegebenen DWORD-Adresse platziert. Andernfalls wird der Ausgangscode in dieser Adresse platziert.
Das Abrufen des Ausgangscodes von CWinThread-Objekten erfordert einen zusätzlichen Schritt. Standardmäßig wird bei Beendung eines CWinThread
-Threads das entsprechende Threadobjekt gelöscht. Dies bedeutet, dass Sie nicht mehr auf den m_hThread
-Datenmember zugreifen können, da das CWinThread
-Objekt nicht mehr vorhanden ist. Führen Sie zur Vermeidung dieser Situation einen der folgenden Schritte aus:
Legen Sie das
m_bAutoDelete
Datenelement auf FALSE fest. Auf diese Weise ist einCWinThread
-Objekt auch nach dem Beenden des Threads noch vorhanden. Sie können dann auf denm_hThread
-Datenmember zugreifen, nachdem der Thread beendet wurde. Bei dieser Methode müssen Sie das Zerstören desCWinThread
-Objekts selbst übernehmen, da es nicht automatisch vom Framework gelöscht wird. Dies ist die bevorzugte Methode.Speichern Sie das Handle des Threads separat. Kopieren Sie nach dem Erstellen des Threads dessen
m_hThread
Datenmemm (mithilfe::DuplicateHandle
von ) in eine andere Variable, und greifen Sie über diese Variable darauf zu. Auf diese Weise wird das Objekt automatisch bei Beendigung gelöscht, und Sie haben dennoch die Möglichkeit, den Grund für die Beendigung des Threads zu ermitteln. Achten Sie darauf, dass der Thread nicht beendet wird, bevor Sie die Möglichkeit hatten, das Handle zu duplizieren. Dies ist die sicherste Möglichkeit, CREATE_SUSPENDED an AfxBeginThread zu übergeben, das Handle zu speichern und dann den Thread fortzusetzen, indem Sie ResumeThread aufrufen.
Bei beiden Methoden lässt sich ermitteln, warum ein CWinThread
-Objekt beendet wurde.
Siehe auch
Multithreading mit C++ und MFC
_endthread, _endthreadex
_beginthread, _beginthreadex
ExitThread