• 本站由于前段时间遭受到大量临时和国外邮箱注册,所以对可注册的邮箱类型进行了限制!

  • 欢迎大家交换友链,可在https://www.stubbornhuang.com/申请友情链接进行友链交换申请!

  • 计算机图形学与计算几何经典必备书单整理,下载链接可参考:https://www.stubbornhuang.com/1256/

  • 在本站开通年度VIP,无限制下载本站资源和阅读本站文章

  • 感谢大家访问本站,希望本站的内容可以帮助到大家!

  • 如果觉得本站的内容有帮助,可以考虑打赏博主哦!

  • 本站会放置Google广告用于维持域名以及网站服务器费用。

  • 问题反馈可发送邮件到stubbornhuang@qq.com

  • 工资「喂饱肚子」,副业「养活灵魂」!

C++ – 主线程如何捕获子线程抛出的异常

C++ 发布于2023-06-30 阅读 4,997次 0次评论 0次点赞 本文共2117个字,阅读需要6分钟。

1 C++抛出异常与捕获异常

在C++中我们经常使用以下代码抛出异常和捕获异常

#include <iostream>
#include <thread>
#include <exception>
#include <stdexcept>

int main()
{
    try
    {
        throw std::runtime_error("Exception: runtime error in thread");
    }
    catch (const std::exception& ex)
    {
        std::cout << "Exited with exception: " << ex.what() << "\n";
    }

    return 0;
}

上述抛出代码和捕获代码都是在主线程中进行了,我们能够顺利的捕捉到抛出的异常。

那如果我在子线程中抛出异常,在主线程中能捕捉到吗?

C++主线程无法捕获子线程异常!!!

C++在子线程中抛出异常是无法在主线程捕获到的,看以下示例代码

#include <iostream>
#include <thread>
#include <exception>
#include <stdexcept>

void StartThread()
{
    throw std::runtime_error("Exception: runtime error in thread");
}

int main()
{
    try
    {
        std::thread thread(StartThread);
        thread.join();
    }
    catch (const std::exception& ex)
    {
        std::cout << "Thread exited with exception: " << ex.what() << "\n";
    }

    return 0;
}

执行程序,没有输出任何内容,这说明C++中子线程中抛出的异常无法在主线程中捕获,也就是说一个线程中抛出的异常只能在同一线程捕获。

2 C++如何在主线程中捕获子线程抛出的异常

上面我们了解了在C++中不能在主线程中捕捉到子线程抛出的异常,那么如果业务强制要求需要在主线程中捕获子线程的异常,那么我们该如何实现呢?

理想的一个设计是:

  • 在主线程中声明一个变量,将该变量传递到子线程中
  • 在子线程抛出异常的时候,修改变量的值为异常值
  • 然后在主线程中捕获异常

基于上面的设计,我们使用std::promise来完成这一实现,先看代码

#include <iostream>
#include <thread>
#include <exception>
#include <stdexcept>
#include <future>

void StartThread(std::promise<void>& promise)
{
    try {
        std::this_thread::sleep_for(std::chrono::seconds(5));
        throw std::runtime_error("Exception: runtime error in thread");
        promise.set_value();
    }
    catch (...)
    {
        promise.set_exception(std::current_exception());
    }
}

int main()
{
    std::promise<void> exception_promise;
    std::thread thread(std::bind(StartThread, std::ref(exception_promise)));

    std::future<void> exception_future = exception_promise.get_future();

    // 等待子线程执行完成
    for (int i = 0; ; i++)
    {
        if (exception_future.wait_for(std::chrono::seconds(1)) != std::future_status::timeout)
            break;
        std::cout << "waiting ... [" << i << "] seconds" << std::endl;
    }

    try
    {
        exception_future.get();
    }
    catch (const std::exception& e)
    {
        std::cout << "Thread exited with exception: " << e.what() << "\n";
    }

    thread.join();

    return 0;
}

上述代码成功在主线程中捕获到了子线程抛出的异常,运行日志如下

waiting ... [0] seconds
waiting ... [1] seconds
waiting ... [2] seconds
waiting ... [3] seconds
Thread exited with exception: Exception: runtime error in thread

在上述代码中,我们在主线程中声明了一个std::promiss<void>类型的变量,并传递到子线程中,然后在子线程中使用try catch语句捕获异常然后设置给std::promise<void>变量;而在主线程中我们使用std::future获取到std::promise的future,然后使用try catch成功捕捉到设置到std::promise<void>变量中的异常。

欢迎扫码关注我的微信公众号,及时获取文章更新

微信公众号二维码

本文作者:StubbornHuang

版权声明:本文为站长原创文章,如果转载请注明原文链接!

原文标题:C++ – 主线程如何捕获子线程抛出的异常

原文链接:https://www.stubbornhuang.com/2713/

发布于:2023年06月30日 13:40:10

修改于:2023年06月30日 13:40:10

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

文章末尾
上一篇
OpenCV - OpenCV打开摄像头显示摄像头帧率
C++
下一篇
如何获取CUDA版本号?CUDA Driver Version和CUDA Runtime Version的区别是什么?
其他
当前分类随机文章推荐

发表评论

您必须 [ 登录 ] 才能发表留言!

关注我们的公众号

微信公众号