usar threads thread libreria ejemplos ejemplo algorithms c++ multithreading c++11 stdthread

libreria - threads c++>



¿Cómo comprobar si un hilo std:: todavía se está ejecutando? (5)

¿Cómo puedo verificar si un std::thread todavía se está ejecutando (de una manera independiente de la plataforma)? Carece de un método timed_join() y joinable() no está destinado para eso.

Pensé en bloquear un mutex con std::lock_guard en el hilo y usar el método try_lock() del mutex para determinar si todavía está bloqueado (el hilo se está ejecutando), pero me parece innecesariamente complejo.

¿Conoces un método más elegante?

Actualización: para ser claro: quiero verificar si el hilo salió limpiamente o no. Se considera que un subproceso ''colgado'' se ejecuta para este fin.


Cree un mutex al que tengan acceso el subproceso en ejecución y el subproceso de llamada. Cuando se inicia el hilo en ejecución, bloquea el mutex y, cuando termina, desbloquea el mutex. Para verificar si el hilo todavía se está ejecutando, el hilo de llamada llama a mutex.try_lock (). El valor de retorno de eso es el estado del hilo. (Solo asegúrate de desbloquear el mutex si el try_lock funcionó)

Un pequeño problema con esto, mutex.try_lock () devolverá falso entre el momento en que se crea el hilo y cuando bloquea el mutex, pero esto se puede evitar usando un método un poco más complejo.


Este mecanismo simple puede usar para detectar el acabado de un hilo sin bloquear en el método de unión.

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


Seguramente tiene una variable envuelta en mutex inicializada en false , que el hilo se establece en true como la última cosa que hace antes de salir. ¿Es eso lo suficientemente atómico para tus necesidades?


Si está dispuesto a utilizar C ++ 11 std::async y std::future para ejecutar sus tareas, entonces puede utilizar la función wait_for de std::future para comprobar si el hilo todavía se ejecuta de forma ordenada. Me gusta esto:

#include <future> #include <thread> #include <chrono> #include <iostream> 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. }

Si debe usar std::thread , puede usar std::promise para obtener un objeto futuro:

#include <future> #include <thread> #include <chrono> #include <iostream> int main() { using namespace std::chrono_literals; // Create a promise and get its future. std::promise<bool> 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. }

Ambos ejemplos darán como resultado:

Thread still running

Esto es, por supuesto, porque el estado del hilo se verifica antes de que la tarea finalice.

Pero, de nuevo, podría ser más simple hacerlo como otros ya lo han mencionado:

#include <thread> #include <atomic> #include <chrono> #include <iostream> int main() { using namespace std::chrono_literals; std::atomic<bool> 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. }

Editar:

También está la std::packaged_task para usar con std::thread para una solución más limpia que usando std::promise :

#include <future> #include <thread> #include <chrono> #include <iostream> int main() { using namespace std::chrono_literals; // Create a packaged_task using some task and get its future. std::packaged_task<void()> 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. }


Una solución fácil es tener una variable booleana que el hilo establezca en verdadero en intervalos regulares, y que esté marcada y configurada en falso por el hilo que desea conocer el estado. Si la variable es falsa por demasiado tiempo, el hilo ya no se considera activo.

Una forma más segura de subprocesos es tener un contador que se incrementa mediante el subproceso secundario, y el subproceso principal compara el contador con un valor almacenado y si es el mismo después de demasiado tiempo, el subproceso secundario se considera no activo.

Sin embargo, tenga en cuenta que no hay forma de que C ++ 11 mate o elimine realmente un hilo colgado.

Editar Cómo comprobar si un hilo ha salido limpiamente o no: básicamente la misma técnica que se describe en el primer párrafo; Tener una variable booleana inicializada en falso. Lo último que hace el subproceso secundario es establecerlo en verdadero. El hilo principal puede verificar esa variable, y si es verdadero, unir en el hilo hijo sin mucho (si hay) bloqueo.

Edit2 Si el hilo sale debido a una excepción, entonces tiene dos funciones "principales" de hilo: la primera tiene un try - catch dentro del cual llama a la segunda función de hilo principal "real". Esta primera función principal establece la variable "have_exited". Algo como esto:

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