从线程捕获异常时退出程序
Posted
技术标签:
【中文标题】从线程捕获异常时退出程序【英文标题】:Exit program when catch exception from thread 【发布时间】:2018-03-16 03:59:14 【问题描述】:参考Catching exception from worker thread in the main thread,我创建了一个工作线程,它向主线程抛出异常然后终止程序(逻辑是在发生异常时退出程序)。
我似乎没有正确实现它,因为程序直到调用 exit() 的那一行才会执行。
示例代码:
#include <thread>
#include <iostream>
#include <stdexcept>
static std::exception_ptr _exceptionPtr = nullptr;
struct WorkerThread
std::thread thread;
void doSomething()
int seconds = 0;
bool shouldStop = false;
while(shouldStop == false)
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "time passed : " << ++seconds << "seconds" << std::endl;
if (seconds == 10) // something bad happened 10 seconds later
try
shouldStop = true;
throw std::runtime_error("something really bad happened");
catch (const std::runtime_error &ex)
_exceptionPtr = std::current_exception();
void run()
thread = std::thread([this] doSomething(); );
thread.detach();
;
int main(int argc, char *argv[])
WorkerThread workerThread;
try
workerThread.run();
catch (...)
if (_exceptionPtr)
try
std::rethrow_exception(_exceptionPtr);
catch (std::runtime_error &ex)
// terminates program if exception happens
std::cout << "Program will now exit" << std::endl;
exit(EXIT_FAILURE); // but program never executes till here
for (;;)
// do A
// do B
// do C
// do ...
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "waiting for thread..." << std::endl;
return 0;
我错过了什么?当前的方法是否正确?如果没有,我该怎么做?谢谢
【问题讨论】:
你需要在for循环中测试worker线程是否出错,而不是for run()函数,它会立即返回。 How can I propagate exceptions between threads?的可能重复 看起来工作线程实际上并没有在抛出。您正在捕获异常并设置共享 ptr,但不会重新抛出。我看不出你在 .run 周围的捕获有什么可捕获的。 您是否考虑过将回调函数传递给线程并让它以这种方式报告错误? @liliscent 你是对的 【参考方案1】:在您发布的代码中,异常检查仅发生一次,并且可能在线程启动之前发生。
您还从主机线程中捕获了一个错误,但您抛出的错误是在第二个线程上。
我通过在检查异常之前等待第二个线程完成来解决了这些问题。
无论如何,跨线程抛出异常的典型方法可以在这里找到:How can I propagate exceptions between threads?
#include <thread>
#include <iostream>
#include <stdexcept>
static std::exception_ptr _exceptionPtr = nullptr;
struct WorkerThread
std::thread thread;
void doSomething()
int seconds = 0;
bool shouldStop = false;
while (shouldStop == false)
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "time passed : " << ++seconds << "seconds" << std::endl;
if (seconds == 10) // something bad happened 10 seconds later
try
shouldStop = true;
throw std::runtime_error("something really bad happened");
catch (const std::runtime_error &ex)
_exceptionPtr = std::current_exception();
void run()
thread = std::thread([this] doSomething(); );
//thread.detach();
;
int main(int argc, char *argv[])
WorkerThread workerThread;
workerThread.run();
workerThread.thread.join();
if (_exceptionPtr)
try
std::rethrow_exception(_exceptionPtr);
catch (std::runtime_error &ex)
// terminates program if exception happens
std::cout << "Program will now exit" << std::endl;
exit(EXIT_FAILURE); // but program never executes till here
for (;;)
// do A
// do B
// do C
// do ...
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "waiting for thread..." << std::endl;
return 0;
【讨论】:
我可能错了,但是如果让主机线程等待工作线程完成,它不会失去线程的意图吗?我希望它们同时运行。 @HohoHaha 在这种情况下是的,但一般来说不是。您可以在调用等待命令之前完成工作。你可以有不止一个线程在等待。如果发生错误,您还可以有一个轮询循环。【参考方案2】:应该在 for 循环而不是 workerThread.run() 中捕获异常,因为 run() 将立即退出。
#include <thread>
#include <iostream>
#include <stdexcept>
static std::exception_ptr _exceptionPtr = nullptr;
struct WorkerThread
std::thread thread;
void doSomething()
int seconds = 0;
bool shouldStop = false;
while (shouldStop == false)
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "time passed : " << ++seconds << "seconds" << std::endl;
if (seconds == 10) // something bad happened 10 seconds later
try
shouldStop = true;
throw std::runtime_error("something really bad happened");
catch (const std::runtime_error &ex)
_exceptionPtr = std::current_exception();
void run()
thread = std::thread([this] doSomething(); );
thread.detach();
;
int main(int argc, char *argv[])
WorkerThread workerThread;
workerThread.run();
for (;;)
// do A
// do B
// do C
// do ...
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
std::cout << "waiting for thread..." << std::endl;
if (_exceptionPtr)
try
std::rethrow_exception(_exceptionPtr);
catch (std::runtime_error &ex)
// terminates program if exception happens
std::cout << "Program will now exit" << std::endl;
exit(EXIT_FAILURE); // but program never executes till here
return 0;
感谢@liliscent
【讨论】:
以上是关于从线程捕获异常时退出程序的主要内容,如果未能解决你的问题,请参考以下文章
Android视图:未捕获的处理程序:线程主因未捕获的异常而退出