Как да проверите дали е възникнало изключение в един от нишките?
Отговор от AI
sobes.tech AI
За проверка на изключение в нишка, могат да се използват няколко подхода, в зависимост от това как е създадено нишката и как се обработват резултатите й.
-
Използване на
std::futureиstd::async: Ако нишката е стартирана с помощта наstd::async, резултатът ще бъде обектstd::future. Викайки методитеget()илиwait()върху този обект, ще се повтори изключението, хвърлено в нишката.#include <future> #include <iostream> #include <stdexcept> void thread_function() { throw std::runtime_error("Грешка в нишката!"); } int main() { std::future<void> future = std::async(std::launch::async, thread_function); try { future.get(); // Изчаква завършване и хвърля изключение, ако е имало } catch (const std::exception& e) { std::cerr << "Изключение, хванато от нишката: " << e.what() << std::endl; } return 0; } -
Използване на
std::promiseиstd::future: Може явно да се предадеstd::promiseкъм нишката или да се съхранява извън нея, за да може нишката да запази изключението.#include <future> #include <iostream> #include <thread> #include <stdexcept> void thread_function_with_promise(std::promise<void>&& promise) { try { throw std::runtime_error("Още една грешка в нишката!"); promise.set_value(); // Задава стойност (ако не беше изключение) } catch (...) { promise.set_exception(std::current_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(); // Изчаква завършване и хвърля запазеното изключение } catch (const std::exception& e) { std::cerr << "Изключение, хванато от нишката (с помощта на promise): " << e.what() << std::endl; } t.join(); // Изчаква завършването на нишката return 0; } -
Ръчно управление на изключения: Нишката може да улови изключението вътре в себе си и да го запази (например, в
std::exception_ptr) или да уведоми друга нишка за неговото възникване (например, чрез атомарна променлива или мьютекс с условна променлива).#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("Логическа грешка в нишката!"); } catch (...) { std::lock_guard<std::mutex> lock(exception_mutex); global_exception_ptr = std::current_exception(); // Запазва текущото изключение exception_occurred = true; exception_cv.notify_one(); // Уведомява чакащата нишка } } int main() { std::thread t(thread_function_manual); // Основната нишка може да чака уведомление за изключение 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); // Повторно хвърля запазеното изключение } catch (const std::exception& e) { std::cerr << "Изключение, хванато от нишката (ръчно управление): " << e.what() << std::endl; } } t.join(); return 0; }
Изборът на метод зависи от контекста: std::async с std::future е най-удобен за получаване на резултат или изключение от отделна задача, докато std::promise/std::future или ръчно управление могат да бъдат полезни в по-сложни сценарии за синхронизация.