Comment vérifier si une exception s'est produite dans l'un des threads?
Réponse de l'IA
sobes.tech IA
Pour vérifier les exceptions dans un thread, plusieurs approches peuvent être utilisées en fonction de la façon dont le thread a été créé et de la gestion de ses résultats.
-
Utilisation de
std::futureetstd::async: Si le thread a été lancé avecstd::async, le résultat sera un objetstd::future. Appeler les méthodesget()ouwait()sur cet objet entraînera la relance de l'exception levée dans le thread dans le thread appelant.#include <future> #include <iostream> #include <stdexcept> void thread_function() { throw std::runtime_error("Erreur dans le thread!"); } int main() { std::future<void> future = std::async(std::launch::async, thread_function); try { future.get(); // Attend la fin et relance l'exception si elle existe } catch (const std::exception& e) { std::cerr << "Exception capturée du thread: " << e.what() << std::endl; } return 0; } -
Utilisation de
std::promiseetstd::future: Il est possible de passer explicitement unstd::promiseau thread ou de le garder en dehors pour que le thread puisse sauvegarder l'exception.#include <future> #include <iostream> #include <thread> #include <stdexcept> void thread_function_with_promise(std::promise<void>&& promise) { try { throw std::runtime_error("Une autre erreur dans le thread!"); promise.set_value(); // Définir la valeur (si pas d'exception) } catch (...) { promise.set_exception(std::current_exception()); // Sauvegarder l'exception } } int main() { std::promise<void> promise; std::future<void> future = promise.get_future(); std::thread t(thread_function_with_promise, std::move(promise)); try { future.get(); // Attend la fin et relance l'exception sauvegardée } catch (const std::exception& e) { std::cerr << "Exception capturée du thread (avec promise): " << e.what() << std::endl; } t.join(); // Attend la fin du thread return 0; } -
Gestion manuelle des exceptions: Le thread peut attraper l'exception en interne et la sauvegarder (par exemple, dans
std::exception_ptr) ou en informer un autre thread (par exemple, via une variable atomique ou un mutex avec une variable conditionnelle).#include <iostream> #include <thread> #include <atomic> #include <exception> #include <mutex> #include <condition_variable> std::exception_ptr global_exception_ptr = nullptr; std::mutex exception_mutex; std::condition_variable exception_cv; bool exception_occurred = false; void thread_function_manual() { try { throw std::logic_error("Erreur logique dans le thread!"); } catch (...) { std::lock_guard<std::mutex> lock(exception_mutex); global_exception_ptr = std::current_exception(); // Sauvegarder l'exception courante exception_occurred = true; exception_cv.notify_one(); // Notifier le thread en attente } } int main() { std::thread t(thread_function_manual); // Le thread principal peut attendre la notification de l'exception std::unique_lock<std::mutex> lock(exception_mutex); exception_cv.wait(lock, []{ return exception_occurred; }); if (global_exception_ptr) { try { std::rethrow_exception(global_exception_ptr); // Relancer l'exception sauvegardée } catch (const std::exception& e) { std::cerr << "Exception capturée du thread (gestion manuelle): " << e.what() << std::endl; } } t.join(); return 0; }
Le choix de la méthode dépend du contexte : std::async avec std::future est le plus pratique pour obtenir un résultat ou une exception d'une tâche séparée, tandis que std::promise/std::future ou la gestion manuelle peuvent être utiles dans des scénarios de synchronisation plus complexes.