我如何暂停异常传播,直到单独的std :: thread完成?

问题描述 投票:1回答:1

我的代码分为一个部分在主线程中运行,另一部分在单独的线程中。主线程最后等待thread.join()

现在,如果主线程抛出异常,即使我尝试捕获异常,我的程序也会立即终止。我将其跟踪到std::~thread,如果线程仍在运行(可连接),这将不令人满意。

在这种情况下,我希望异常能够等到线程自然退出后再继续传播。我怎么做?我是否需要用某种std::thread来包装joining_thread,将其加入?

#include <iostream>
#include <thread>

class foo
{
public:
    foo(const char* name) : m_name(name) {}
    ~foo() { std::cout << "~foo - " << m_name << "\n"; }
private:
    std::string m_name;
};

void doInThread()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "doInThread\n";
}

int doit()
{
    foo fooBefore("main before thread");   // d'tor is never called
    auto thread = std::thread(doInThread);
    foo fooAfter("main after thread");

    // Do stuff, which might throw
    throw std::exception("Something happened in main");

    thread.join();
}

int main()
{
    try
    {
        doit();
    }
    catch (std::exception ex)
    {
        std::cout << "Exception: " << ex.what() << "\n";  // Never happens - program terminates beforehand
    }
}
c++ stdthread
1个回答
1
投票

您的程序通过调用std::terminate函数中止。

当引发异常时,将发生堆栈展开,这意味着将删除在调用throw之前创建的所有局部变量。当调用线程的dtor且线程处于可连接状态时,将调用std::terminate

使用RAII创建其dtor将加入您的线程的对象。

according to thread reference

现在在展开堆栈时,将按以下方式调用析构函数:template<class F> struct Cleaner { Cleaner(F in) : f(in) {} ~Cleaner() { f(); } F f; }; template<class F> Cleaner<F> makeCleaner(F f) { return Cleaner<F>(f); } int doit() { foo fooBefore("main before thread"); auto thread = std::thread(doInThread); auto cleaner = makeCleaner([&thread](){ thread.join(); }); foo fooAfter("main after thread"); throw std::runtime_error("Something happened in main"); // without throw statement, dtor of cleaner instance would be called here } fooAfter(您在其中等待线程完成)和cleaner

© www.soinside.com 2019 - 2024. All rights reserved.