Wie kann ich überprüfen, ob a std::thread
noch ausgeführt wird (plattformunabhängig)? Es fehlt eine timed_join()
Methode und joinable()
ist nicht dafür gedacht.
Ich dachte daran, einen Mutex mit einem std::lock_guard
im Thread zu sperren und mithilfe der try_lock()
Mutex-Methode festzustellen, ob er noch gesperrt ist (der Thread läuft), aber er scheint mir unnötig komplex zu sein.
Kennen Sie eine elegantere Methode?
Update: Um klar zu sein: Ich möchte überprüfen, ob der Thread sauber beendet wurde oder nicht. Zu diesem Zweck wird ein "hängender" Thread als laufend betrachtet.
c++
multithreading
c++11
stdthread
kispaljr
quelle
quelle
wait()
und wenn ja, wenn Sie noch nichtwait()
dafür gearbeitet haben, muss er per Definition ausgeführt werden. Aber diese Argumentation könnte ungenau sein.Antworten:
Wenn Sie bereit sind, C ++ 11 zu verwenden
std::async
undstd::future
Ihre Aufgaben auszuführen, können Sie diewait_for
Funktion verwenden, umstd::future
zu überprüfen, ob der Thread noch ordnungsgemäß ausgeführt wird:Wenn Sie verwenden müssen
std::thread
, können Sie verwendenstd::promise
, um ein zukünftiges Objekt zu erhalten:Beide Beispiele geben Folgendes aus:
Dies liegt natürlich daran, dass der Thread-Status vor Abschluss der Aufgabe überprüft wird.
Andererseits könnte es einfacher sein, es einfach so zu machen, wie andere es bereits erwähnt haben:
Bearbeiten:
Es gibt auch die
std::packaged_task
Verwendungstd::thread
für eine sauberere Lösung als die Verwendung vonstd::promise
:quelle
std::atomic<bool> done(false);
? Ist dasbool
Atom nicht standardmäßig?std::atomic
.sizeof(bool)
Ist die Implementierung definiert und kann> 1 sein, so ist es möglich, dass ein teilweises Schreiben auftritt. Es gibt auch das Problem der Cache-Kohärenz.Eine einfache Lösung besteht darin, eine boolesche Variable zu haben, die der Thread in regelmäßigen Abständen auf true setzt und die von dem Thread, der den Status wissen möchte, überprüft und auf false gesetzt wird. Wenn die Variable zu lange falsch ist, wird der Thread nicht mehr als aktiv betrachtet.
Eine thread-sicherere Möglichkeit besteht darin, einen Zähler zu haben, der vom untergeordneten Thread erhöht wird, und der Haupt-Thread vergleicht den Zähler mit einem gespeicherten Wert. Wenn dieser nach zu langer Zeit derselbe ist, wird der untergeordnete Thread als nicht aktiv betrachtet.
Beachten Sie jedoch, dass es in C ++ 11 keine Möglichkeit gibt, einen hängengebliebenen Thread tatsächlich zu beenden oder zu entfernen.
Bearbeiten So überprüfen Sie, ob ein Thread sauber beendet wurde oder nicht: Grundsätzlich dieselbe Technik wie im ersten Absatz beschrieben; Lassen Sie eine boolesche Variable auf false initialisieren. Das Letzte, was der untergeordnete Thread tut, ist, ihn auf true zu setzen. Der Hauptthread kann dann diese Variable überprüfen und, falls true, einen Join für den untergeordneten Thread ausführen, ohne dass viel (falls vorhanden) blockiert wird.
Edit2 Wenn der Thread aufgrund einer Ausnahme beendet wird, haben Sie zwei "Haupt" -Funktionen des Threads: Die erste hat eine
try
-,catch
in der die zweite "echte" Haupt-Thread-Funktion aufgerufen wird. Diese erste Hauptfunktion setzt die Variable "have_exited". Etwas wie das:quelle
thread_done
, wird dieser Code ohne Speicherbarriere unterbrochen. Verwenden Siestd::atomic<bool>
stattdessen.bool
während der Haupt-Thread daraus liest - dies erfordert eine Speicherbarriere.std::atomic<bool>
erforderlich ist.Mit diesem einfachen Mechanismus können Sie die Fertigstellung eines Threads erkennen, ohne die Join-Methode zu blockieren.
quelle
join()
von einem Thread aus aufrufen , der nicht darauf wartet, dass der Thread seinejoinable()
Eigenschaft verliert, da er sonst endlos wiederholt wird (dhjoinable()
true zurückgibt, bis der Thread tatsächlich istjoin()
ed und nicht bis es fertig ist)thread.detach()
das obige Programm niemals beendet wird, wenn Sie das Teil entfernen .Erstellen Sie einen Mutex, auf den sowohl der laufende Thread als auch der aufrufende Thread Zugriff haben. Wenn der laufende Thread startet, wird der Mutex gesperrt, und wenn er endet, wird der Mutex entsperrt. Um zu überprüfen, ob der Thread noch ausgeführt wird, ruft der aufrufende Thread mutex.try_lock () auf. Der Rückgabewert davon ist der Status des Threads. (Stellen Sie einfach sicher, dass Sie den Mutex entsperren, wenn try_lock funktioniert hat.)
Ein kleines Problem dabei ist, dass mutex.try_lock () zwischen dem Erstellen des Threads und dem Sperren des Mutex false zurückgibt. Dies kann jedoch mit einer etwas komplexeren Methode vermieden werden.
quelle
std::mutex
diese Art der Signalisierung nicht verwenden (hauptsächlich aus Gründen, wie Mutex normalerweise implementiert wird). Einatomic_flag
funktioniert in diesem Fall genauso gut mit viel weniger Aufwand. Astd::future
könnte sogar noch besser sein, da es die Absicht klarer ausdrückt. Denken Sie auch daran, dass diestry_lock
möglicherweise fälschlicherweise fehlschlägt, sodass die Rückgabe nicht unbedingt dem Status des Threads entspricht (obwohl Sie in diesem speziellen Fall wahrscheinlich nicht sehr verletzt werden).Sicherlich muss eine mit Mutex umschlossene Variable initialisiert werden
false
, auf die der Threadtrue
als letztes festgelegt wird, bevor er beendet wird. Ist das atomar genug für Ihre Bedürfnisse?quelle
std::atomic<bool>
kümmert sich darum für Sie, weshalb es die eigentliche Antwort IMO ist.Sie können jederzeit überprüfen, ob sich die ID des Threads von der Standardkonstruktion std :: thread :: id () unterscheidet. Einem laufenden Thread ist immer eine echte ID zugeordnet. Versuche zu viel ausgefallenes Zeug zu vermeiden :)
quelle