gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 09:56:34 30 4
gpt4 key购买 nike

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

现在,如果主线程抛出异常,我的程序会立即终止,即使我 try catch 异常。我追踪到 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
}
}

最佳答案

通过调用 std::terminate 中止您的程序功能。

抛出异常时,堆栈展开,这意味着在调用 throw 之前创建的所有局部变量被删除。当线程的dtor被调用,线程处于joinable状态时,std::terminate被调用 according to thread reference .

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

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 (等待线程完成)和 fooBefore .

关于c++ - 如何暂停异常传播,直到单独的 std::thread 完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59598185/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com