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 ein CWinThread-Objekt auch nach dem Beenden des Threads noch vorhanden. Sie können dann auf den m_hThread-Datenmember zugreifen, nachdem der Thread beendet wurde. Bei dieser Methode müssen Sie das Zerstören des CWinThread-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 ::DuplicateHandlevon ) 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