Wie überprüft man, ob ein std :: -Thread noch läuft?

Wie kann ich überprüfen, ob ein std::thread (plattformunabhängig) noch läuft? Es fehlt eine timed_join() Methode und joinable() ist dafür nicht gedacht.

Ich dachte daran, einen Mutex mit einem std::lock_guard in den Thread zu std::lock_guard und mithilfe der try_lock() -Methode des Mutex festzustellen, ob er noch gesperrt ist (der Thread läuft), aber es erscheint mir unnötig komplex.

Kennst du eine elegantere Methode?

Update: Um klar zu sein: Ich möchte überprüfen, ob der Thread sauber beendet wurde oder nicht. Ein hängender Thread wird zu diesem Zweck ausgeführt.

Solutions Collecting From Web of "Wie überprüft man, ob ein std :: -Thread noch läuft?"

Wenn Sie bereit sind, C ++ 11 std::async und std::future zum Ausführen Ihrer Aufgaben zu verwenden, können Sie die function wait_for von std::future , um zu überprüfen, ob der Thread noch ordnungsgemäß ausgeführt wird so was:

 #include  #include  #include  #include  int main() { using namespace std::chrono_literals; /* Run some task on new thread. The launch policy std::launch::async makes sure that the task is run asynchronously on a new thread. */ auto future = std::async(std::launch::async, [] { std::this_thread::sleep_for(3s); return 8; }); // Use wait_for() with zero milliseconds to check thread status. auto status = future.wait_for(0ms); // Print status. if (status == std::future_status::ready) { std::cout < < "Thread finished" << std::endl; } else { std::cout << "Thread still running" << std::endl; } auto result = future.get(); // Get result. } 

Wenn Sie std::thread , können Sie std::promise , um ein zukünftiges Objekt zu erhalten:

 #include  #include  #include  #include  int main() { using namespace std::chrono_literals; // Create a promise and get its future. std::promise p; auto future = p.get_future(); // Run some task on a new thread. std::thread t([&p] { std::this_thread::sleep_for(3s); p.set_value(true); // Is done atomically. }); // Get thread status using wait_for as before. auto status = future.wait_for(0ms); // Print status. if (status == std::future_status::ready) { std::cout < < "Thread finished" << std::endl; } else { std::cout << "Thread still running" << std::endl; } t.join(); // Join thread. } 

Beide Beispiele werden ausgegeben:

 Thread still running 

Das liegt natürlich daran, dass der Thread-Status geprüft wird, bevor die Aufgabe beendet ist.

Aber es könnte auch einfacher sein, es einfach so zu tun, wie andere es bereits erwähnt haben:

 #include  #include  #include  #include  int main() { using namespace std::chrono_literals; std::atomic done(false); // Use an atomic flag. /* Run some task on a new thread. Make sure to set the done flag to true when finished. */ std::thread t([&done] { std::this_thread::sleep_for(3s); done = true; }); // Print status. if (done) { std::cout < < "Thread finished" << std::endl; } else { std::cout << "Thread still running" << std::endl; } t.join(); // Join thread. } 

Bearbeiten:

Es gibt auch die std::packaged_task zur Verwendung mit std::thread für eine sauberere Lösung als mit std::promise :

 #include  #include  #include  #include  int main() { using namespace std::chrono_literals; // Create a packaged_task using some task and get its future. std::packaged_task task([] { std::this_thread::sleep_for(3s); }); auto future = task.get_future(); // Run task on new thread. std::thread t(std::move(task)); // Get thread status using wait_for as before. auto status = future.wait_for(0ms); // Print status. if (status == std::future_status::ready) { // ... } t.join(); // Join thread. } 

Eine einfache Lösung besteht darin, eine boolesche Variable zu haben, die der Thread in regelmäßigen Intervallen auf true setzt, und die vom Thread, der den Status wissen möchte, aktiviert und auf false gesetzt wird. Wenn die Variable zu lange falsch ist, wird der Thread nicht länger als aktiv betrachtet.

Eine threadsicherere Möglichkeit besteht darin, einen Zähler zu haben, der vom untergeordneten Thread erhöht wird, und der Hauptthread vergleicht den Zähler mit einem gespeicherten Wert und wenn derselbe nach zu langer Zeit verwendet wird, wird der untergeordnete Thread als nicht aktiv betrachtet.

Beachten Sie jedoch, dass es in C ++ 11 keine Möglichkeit gibt, einen gehängten Thread tatsächlich zu beenden oder zu entfernen.

Bearbeiten So überprüfen Sie, ob ein Thread sauber beendet wurde oder nicht: Grundsätzlich die gleiche Vorgehensweise wie im ersten Absatz beschrieben; Lassen Sie eine boolesche Variable auf false initialisiert werden. Das letzte, was der untergeordnete Thread tut, ist True. Der Haupt-Thread kann dann diese Variable überprüfen, und wenn der Wert true ist, wird ein Join für den untergeordneten Thread ohne viel (wenn überhaupt) blockiert.

Edit2 Wenn der Thread aufgrund einer Exception beendet wird, dann haben zwei Thread “Haupt” -functionen: Die erste hat einen trycatch in dem es die zweite “echte” Haupt-Thread-function aufruft. Diese erste Hauptfunktion setzt die Variable “have_exited”. Etwas wie das:

 bool thread_done = false; void *thread_function(void *arg) { void *res = nullptr; try { res = real_thread_function(arg); } catch (...) { } thread_done = true; return res; } 

Dieser einfache Mechanismus kann verwendet werden, um die Fertigstellung eines Threads zu erkennen, ohne in der Join-Methode zu blockieren.

 std::thread thread([&thread]() { sleep(3); thread.detach(); }); while(thread.joinable()) sleep(1); 

Erstellen Sie einen Mutex, auf den der laufende Thread und der aufrufende Thread zugreifen können. Wenn der laufende Thread startet, sperrt er den Mutex, und wenn er beendet wird, entsperrt er den Mutex. 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. (Achten Sie darauf, den Mutex zu entsperren, wenn der try_lock funktioniert)

Ein kleines Problem dabei ist, dass mutex.try_lock () zwischen dem Zeitpunkt, zu dem der Thread erstellt wird, und dem Sperren des Mutex den Wert false zurückgibt. Dies kann jedoch durch eine etwas komplexere Methode vermieden werden.

Stellen Sie sicher, dass eine mutex-umhüllte Variable auf false initialisiert wird, dass der Thread auf ” true als das letzte, was er vor dem Beenden tut. Ist das atomar genug für Ihre Bedürfnisse?