როგორ შემოწმოთ, მოხდა თუ არა გამონაკლისი ერთ-ერთ ნაკადში?
sobes.tech AI
პასუხი 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 կամ ձեռքով կառավարման մեթոդները կարող են օգտակար լինել ավելի բարդ սինխրոնացման դեպքերում։