c++ - 从线程抛出异常没有给出预期的结果

标签 c++ multithreading exception boost

在下面的代码片段中,我试图在重新抛出相同但无法实现相同的异常后捕获异常。我不确定出了什么问题,因为我已经通过 current_exception() 保留了当前的 teptr 状态。线程在连续循环中运行,因此一旦它的值达到更大的 2,就会执行 catch block 并且控制超出循环但仍然如预期的那样我无法在第一次尝试时到达另一个 catch block 。

#include <boost/thread.hpp>
#include <boost/thread/scoped_thread.hpp>
#include <boost/chrono.hpp>
#include <iostream>
#include <boost/exception/all.hpp>
#include <exception>
using namespace std;
boost::exception_ptr teptr;

class myexception : public exception
{
    virtual const char* what() const throw()
    {
        return "My exception happened";
    }
} myex;

class ABC
{
public:
    void start();

};

void ABC::start()
{
    int i = 0;
    cout << "running the thread" << std::endl;

    while (1)
    {
        try
        {
            std::cout << "value of " << i << '\n';

            if (i > 2)
            {
                throw  boost::enable_current_exception(myex);
            }
            i++;
        }
        catch (exception& e)
        {
            cout << "actual exception is" << e.what() << '\n';
            teptr = boost::current_exception();
            break;
            //throw myex;
        }
    }
}

int main()
{
    ABC abc;
    boost::thread thread_point;

    while (1)
    {
        boost::thread thread_point;
        thread_point = boost::thread(&ABC::start, abc);

        if (teptr) {

            try {
                boost::rethrow_exception(teptr);
            }
            catch (const std::exception &ex)
            {
                std::cerr << "Thread exited with exception: " << ex.what() << "\n";
                exit(0);
            }
        }
    }
}

最佳答案

您的程序同时从多个线程访问变量 teptr(以及 myex)而不同步。该行为是未定义的。

更糟糕的是,您正在隐藏 thread_point 并创建许多未连接的线程。您实际上是在运行共享相同全局数据的无限线程。

我想您真的在寻找 future - 允许您从任何地方返回值或异常。所有异常处理魔法都为您完成:

Live On Coliru

#include <thread>
#include <future>
#include <iostream>
#include <sstream>

struct ABC {
    int task(int until) {
        for (int i = 0; i<10; ++i) {
            if (i > until) {
                std::ostringstream oss;
                oss << "My exception happened in thread " << std::this_thread::get_id() << " at i=" << i;
                throw std::runtime_error(oss.str());
            }
        }

        return 42;
    }
};

int main() {
    for (int runs = 0; runs < 10; ++runs) {
        ABC abc;
        std::future<int> result = std::async(&ABC::task, &abc, rand()%20);

        try {
            std::cout << "Task returned " << result.get() << "\n";
        } catch (const std::exception &ex) {
            std::cout << "Task exited with exception: " << ex.what() << "\n";
            std::cerr << "Thread exited with exception: " << ex.what() << "\n";
        }
    }
}

打印(例如):

Task returned Task exited with exception: My exception happened in thread 140288972076800 at i=4
Thread exited with exception: My exception happened in thread 140288972076800 at i=4
Task returned Task exited with exception: My exception happened in thread 140288972076800 at i=7
Thread exited with exception: My exception happened in thread 140288972076800 at i=7
Task returned 42
Task returned 42
Task returned 42
Task returned 42
Task returned Task exited with exception: My exception happened in thread 140288972076800 at i=7
Thread exited with exception: My exception happened in thread 140288972076800 at i=7
Task returned 42
Task returned 42
Task returned Task exited with exception: My exception happened in thread 140288972076800 at i=2
Thread exited with exception: My exception happened in thread 140288972076800 at i=2

关于c++ - 从线程抛出异常没有给出预期的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47856085/

相关文章:

python - Qthread 锁定 Gui PySide

c# - 如何在我的 MSTest 单元测试中检查 "no exception occurred"?

java - 在 Java 中使用 FTP 并检测断开连接

jquery - 如何返回调用 jQuery AJAX 错误函数的错误消息和 HTTP 状态代码?

c++ - 编译共享库时解析 ifdefs

c++ - 如何返回包含 PyObject* 的 boost::python::tuple?

c++ - 模板定义的模板参数数量(非常元)

python - 如何同时运行两个函数

c++ - 如何将小数点分隔符设置为逗号?

java - 用于 Java 线程安全的公共(public)最终互斥锁