Основной поток не может перехватить исключение (выброшенное в основном потоке), пока другой поток с try-catch все еще активен. Как это решить? пример:
int main()
{
// try-catch of main thread
try
{
// run a thread
std::thread cThread([]()
{
// try-catch of secondary thread
try
{
// makes thread works for 500 ms in order main thread will call
// throw while thread is still active.
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
catch (...)
{
}
});
// Any call to throw BEFORE thread is finished, won't be catch.
// HOW TO SOLVE IT??
throw 1;
// wait thread finished
cThread.join();
// IF YOU PUT THE "throw 1" HERE (AFTER THREAD FINISHED), IT WILL BE
// CATCH.
}
catch (int e)
{
std::cout << "Catched exception " << e << " in main";
}
return 0;
}
Дело не столько в том, что исключение не перехватывается, сколько в том, что уничтожение присоединяемого потока завершает процесс. Таким образом, ваша программа завершается до того, как обработчик исключений может быть выполнен.
Если вы объявите поток за пределами блока try-catch, исключение будет перехвачено. Помните, что вам также необходимо присоединиться к потоку, если возникло исключение.
Кстати. it should work
- да, catch
сработает, а ТОГДА завершит программу на return 0
, когда std::thread пройдет внешнюю область видимости :):)
Спасибо, это было правильно. Я изменил его на std::async вместо std::thread.
У тебя что-то не так. Я имею в виду, вы что-то неправильно поняли.
Это не может быть попытка поймать. 'throw' и 'try-catch' - внутрипоточные вещи, они живут только в текущем потоке, каким бы он ни был в момент броска, основным потоком или другим.
Другой поток не может перехватить исключение, созданное текущим потоком. Исключения не пересекаются между потоками, если вы действительно этого не хотите и не реализуете, поскольку, например, что-то в текущем потоке перехватывает исключение и передает их другому потоку, а затем повторно выбрасывает/и т.д. эти исключения там. У вас нет таких вещей, так что это не может быть этим.
У вас есть вызов join()
после броска, и вы ожидаете, что throw 1
пропустит его. Это правда. Однако в области видимости также есть переменная std::thread cThread
.
Поскольку поток запущен и из-за throw 1
поток еще никогда не был присоединен(), то видимая вещь ожидал будет завершение программы (см. https://stackoverflow.com/a/13984169/717732), потому что деструктор std::thread обнаружит un-join( )ред нить. Это означает, что std::cout << "Catched exception " << e << " in main";
никогда не следует вызывать. Даже если поток каким-то образом завершился, ваша программа все равно должна завершиться, так как это не меняет того факта, что она не была объединена (см. https://en.cppreference.com/w/cpp/thread/thread/joinable)
Однако в зависимости от библиотеки, компилятора, отладчика и т. д. видимый эффект может отличаться. Например, если вы запустите его в отладчике, он может дождаться завершения всех потоков, и вы получите эффект «ожидания завершения внутреннего потока». Тяжело сказать.
Если вы действительно видите бегущую строку "Catched exception " << e << "
, у вас настоящая проблема. Либо вы используете что-то другое, чем ваш текущий код, либо ваша stdlib не работает. Сломанная stdlib может, например, выполнять молчаливую функцию join() в деструкторе std::thread вместо завершения программы. Кто знает. Сломанная библиотека может делать многое.
Спасибо, это было правильно. Я изменил его на std::async вместо std::thread.
Спасибо Молбднило и кетцалькоатль. Теперь я заставил код работать, используя std::async вместо std::thread:
Во-первых, проблема не связана с try-catch в потоке. Это была моя ошибка думать, что это так. Итак, вот код неисправности:
int main()
{
// try-catch of main thread
try
{
// run a thread
std::thread cThread([]()
{
});
// Any call to throw BEFORE thread join won't be catch.
// HOW TO SOLVE IT??
throw 1;
// wait thread finished
cThread.join();
// IF YOU PUT THE "throw 1" HERE (AFTER THREAD FINISHED), IT WILL BE
// CATCH.
}
catch (int e)
{
std::cout << "Catched exception " << e << " in main";
}
return 0;
}
И код, который работает:
int main()
{
std::future<void> cF;
// try-catch of main thread
try
{
// run a thread
cF = std::async(std::launch::async, []()
{
});
// You can call throw , it will be catch :)
throw 1;
// wait thread finished
if (cF.valid())
{
cF.get();
}
}
catch (int e)
{
std::cout << "Catched exception " << e << " in main";
}
return 0;
}
хм.. теперь думаю об этом, возможно,
thread.detach()
перед броском тоже сработает.. но хм.. мне не нравится ни одно из решений..