Stoppen Sie thread-sicher
ich Schreibe multi-thread-Programm.
Ich möchte Sie Fragen, was ist der Unterschied zwischen TerminateThread
und ExitThread
?
Dies ist mein code-snippet, wenn WM_DESTROY
erhalten :
void CleanAll()
{
DWORD dwExit[MAX_THREAD];
for(int i = 0; i < MAX_THREAD; i++)
{
GetExitCodeThread(hThread[i], &dwExit[i]);
//I used ExitThread(dwExit[i]); previously
TerminateThread(hThread[i], dwExit[i]);
CloseHandle(hThread[i]);
}
}
Ich verwendet ExitThread()
zuvor, aber mein Programm stikk, die im Task-Manager, so dass ich es ändern zu TerminateThread()
und mein Programm ist Weg aus dem Task-Manager.
Vorauszahlungen, Erklärung ist sehr geschätzt.
Du musst angemeldet sein, um einen Kommentar abzugeben.
TerminateThread Kräfte einem anderen thread zu beenden. Sie sollten vermeiden, fordern Sie unter allen Umständen, wie es halt ein thread tot in seiner tracks ohne chance auf Bereinigung. Dies umfasst alle CRT-Speicher.
ExitThread ist für die aktuell ausgeführten thread zu stoppen, sich selbst schön und sauber. Wenn du Sie genannt hast, die oben sind, haben Sie wahrscheinlich gezwungen, die main (UI) - thread zu beenden, und wahrscheinlich verließen die Laufenden threads noch Verweilen um. Daher, Ihr Programm noch ausgeführt wurde, belegt die im Task-Manager. GetExitCodeThread war wahrscheinlich auch scheitern, da die threads hatte eigentlich nicht verlassen.
Aber der richtige Weg zu stoppen, einen thread sauber zu signal von einem sauberen Mitteln erforderlich, die es verlassen. Dann lassen sich die threads beenden, sich auf Ihre eigenen, bevor der Haupt-thread beenden. Im folgenden Beispiel habe ich ein globales flag, um anzuzeigen, dass threads, die Sie sollten sich verlassen. Aber geht davon aus, dass deine threads werden immer eine chance haben, die Umfrage für die Globale bool Zustand. Einen anderen Reiniger, der Ansatz ist von jedem thread-Aufruf von WaitForSingleObject auf ein Ereignis-handle. Wenn die Ereignis-handle signalisiert wird, wird der thread prüft die Globale variable und beendet Sie, falls erforderlich.
volatile
. Compiler im Allgemeinen optimieren, Schleifen, daher die anderen threads können nicht sehen, einen aktualisierten Wert. Durch die Deklaration einer variablevolatile
sagen Sie dem compiler, dass es wieder Lesen, den Wert vom Speicherort jedes mal, anstatt davon ausgehen, der zuvor gelesene Wert aus einem Prozessor-register oder cache. Andere als die, großartige Antwort! +1volatile
hat verschiedene Bedeutungen in verschiedenen Compiler verwende ichstd::atomic<bool>
. Ich sehe keine Notwendigkeit für eine Zustand-variable.Sorry, aber die top-Antwort gestimmt, sagt zu ExitThread, weil es "halt selbst schön und sauber".
Dies ist einfach nicht wahr. Die Dokumentation besagt:
ExitThread ist die bevorzugte Methode zum beenden eines Threads in C-code. Aber in C++ - code, der thread wird beendet, bevor alle Destruktoren aufgerufen werden kann, oder andere automatische Bereinigung durchgeführt werden kann. Also in C++ - code, sollten Sie Sie wieder aus deinem thread-Funktion.
Ich lernte auf die harte Weise, indem Sie die folgenden Ratschläge aus einem forum nutzen ExitThread und dann stundenlang Fragen, wo zum Teufel alle meine memory leaks aus kamen. Ja, das ist für C++, aber das ist, was diese Frage betrifft. Und tatsächlich, auch für C gibt es eine Einschränkung "Ein thread in dem eine ausführbare Datei, die mit der statischen Bibliothek der C-Laufzeit (CRT) sollte man _beginthread und _endthread für die thread-Verwaltung statt CreateThread und ExitThread. Fehler dazu führt in kleinen Speicherlecks, wenn der thread ruft ExitThread."
VERWENDEN Sie NICHT ExitThread, ohne Kenntnis der Folgen!
Ist Ihr Prozess soll sich beenden, wenn der thread fertig ist? Es könnte eine Menge von Erklärungen für das problem, das Sie beschrieben. Wenn Sie möchten, beenden Sie den gesamten Prozess haben, rufen Sie einfach
ExitProcess
.Das problem mit
TerminateThread
ist, dass es sehr wahrscheinlich einen Speicherverlust verursachen. Es kümmert sich nicht um die thread-Staat, noch seine Mittel zu. Es kann auch einen deadlock verursachen, je nachdem, wie du tust-synchronisation. In anderen Worten, es nicht kündigen würde.Der beste Weg, um zu beenden ein Faden ist, nicht kündigen, es ausdrücklich. Rufen Sie nicht
TerminateThread
nochExitThread
, aber nurreturn
von der thread-Funktion. Sie verwenden müssen, um eine Atom-fahne, oder ein Ereignis ausgelöst (oder ein anderes Synchronisations-Methode), um zu signalisieren, wenn der thread beendet werden soll. Dann ist dein thread sollte in regelmäßigen Abständen überprüfen Sie, dass die Flagge (oder ein Ereignis) und freigeben aller Ressourcen vor der Rückkehr (beenden).Können Sie SingleWaitObjects oder QueueUserAPC aber Sie müssen sicherstellen, dass die den thread Stoppt, um zu überprüfen, die asynchronen Objekte oder warten ein Ende und kündigen den thread normal .. in linux können Sie die Signale von
Schließlich, Sie brauchen, um jeden thread wie ein mini-Prozess (das ist, was Sie unter der Haube sowieso). Um es zu bekommen, um das Herunterfahren sauber, benötigen Sie zusätzliche Infrastruktur im Ort, lassen Sie - der Haupt-thread - sagen, es zu stoppen.
Der einfachste Weg, dies zu tun Recht ist ein signalisierungssystem, das die Erfinder von POSIX herausgefunden, frühzeitig und damit setzen Sie direkt in der OS. Die besten realen Beispiel eines solchen Systems ist die US-Post. Jeder agent besitzt eine eindeutige Adresse aus, die Sie senden und empfangen von E-Mails (Signale) von anderen Adressen, und es ist an den Agenten zu entscheiden, was Sie tun, wenn Sie ein signal bekommen. Einige sind info-oder junk-und damit ignoriert, während andere eine hohe Priorität, und Sie ignorieren Sie auf eigene Gefahr.
In einem code-Ebene müssen Sie die folgenden zu machen, die gut funktionieren (ich habe gebaut, ein paar von diesen für Bildbearbeitungsprogramme):
1) eine abstrakte "Ereignis" oder "ControlSignal" - Objekt. Fühlen Sie sich frei, verwenden Sie die Standard-Windows Ereignisse-oder linux-Signale, wenn Sie angemessen ist.
2) Ein "Rohr" von einer Art: Das OS wird oft eine wörtliche Kernel primitiv BEZEICHNET ein Rohr, mit 1 Ende ziehen die Daten ab, während ein anderer legt Daten in. Dieser Typ ist in der Regel overkill für die Kommunikation innerhalb eines Prozesses, sondern das Objekt, das Sie brauchen, ist konzeptionell entspricht.
3) Code in die threads, ruft Signale aus der Leitung und wirkt auf Sie.
4) Eine "stop" oder "Abbrechen" - signal alle threads erkennen.
Natürlich, Sie KÖNNEN nur schwer Abbrechen ein thread mit TerminateThread genauso, wie Sie Sie verwenden können, taskkill oder STRG-C auf Prozess beenden. ExitThread wird eine Windows-spezifische Art und Weise zu bauen, die einen sauberen shutdown-signal, wie ich beschreiben in (4), aber Sie müssen noch die while-Schleife & "WaitForSingleObject" (3), sowie die Windows-spezifischen handle (2), damit es funktioniert.