Страницы

Поиск по вопросам

среда, 29 января 2020 г.

Как правильно обработать исключение в нескольких потоках?

#cpp #многопоточность #исключения




Можно ли запускать потоки внутри
    try{}?


И что делать, когда
    посылается исключение? Ждать
    завершения других потоков?


Есть ли в std::thread механизм для останова
    всех потоков, ну или конкретные инструменты для решения подобной
    проблемы? Или всё вручную придется делать?
try{ 
// стартуют потоки
   }catch(std::exception исключение)
{
std::cout << "...";
}

поток1
{
// при вызове ведет к неопределенному поведению.
// может выполнится может нет
throw std::exception(строка); 
}

поток2
{
throw std::exception(строка);
}





А как мне в главный поток отрапортовать? о том что произошло исключение в потоке1?
Глобальными переменными?
    try
    { 
// стартуют потоки
    поток1;
    поток2;

    // здесь вечный цикл  
    while(true)
    {
    ... основной поток
    };

    }catch(std::exception исключение)
    {
    std::cout << "...";
    }

    поток1
    {
    try{
    ..
    throw std::exception(строка); 
    ..
    }
    catch(std::exception исключение)
    {

    }
    }

    поток2
    {
    try{
    ..
    throw std::exception(строка);
    ..
    }
    catch(std::exception исключение)
    {
    }

    }
    


Ответы

Ответ 1



Вы не должны смотреть на исключения, как на проблему, с которой нужно "бороться". Исключения -- ваш друг. Это сигнал об ошибке, которую вы должны обработать. Функцию, реализующую логику потока, можно обернуть в try/catch, если это соответствует вашим целям. Можно ловить ошибки и в других местах. Заметьте, что try/catch вокруг запуска потоков не ловит исключения, случившиеся в потоке. Вам нужно завести try/catch в самой главной функции потока. (Спасибо @avp, который подметил это.) По поводу того, что делать, когда произошло исключение в потоке, ответ такой же, как и на вопрос, что делать если вообще произошло исключение. Вы должны поймать исключение, определить, что за ошибка произошла, и отреагировать соответственно этому. Общего рецепта нету и быть не может. Может быть, надо послать центральной логике программы сигнал о том, что программу надо немедленно завершить. Может быть, надо вывести запись в лог и повторить последнюю операцию. Может быть, надо проинформировать пользователя, и переспросить правильные параметры. Может быть, ошибку можно игнорировать. Останавливать другие потоки за вас никто не сможет, да и неправильно это -- вдруг поток держит lock или находится в середине критической операции? Если надо, остановите потоки самостоятельно. Заметьте, остановка остальных потоков в ответ на исключение очень редко бывает правильным решением.

Ответ 2



1) да, но это обработает только проблемы запуска, но не самого потока 2) обрабатывать. Но по месту, в нужном потоке. Каждый поток продолжит исполнение. 3) Поток должен останавливать себя сам.

Ответ 3



Можно, но исключения выкинутые из потока в месте вызова не поймаются. Это просто невозможно т.к. начиная с точки создания код выполняется параллельно. Если исключение выйдет за границы первичной функции потока, вызовется std::terminate (Cтандарт 15.5.1, 30.3.1.2/4). Зависит от задачи и от политики обработки ошибок. Можно аварийно завершаться (действие по умолчанию), можно например сделать обертку над потоком, который ловит все не отловленные исключения и сигнализирует о них упрощенный пример. Или же есть замечательные std::future, std::packaged_task, std::async пример

Комментариев нет:

Отправить комментарий