这是我的问题的延续:Thread creation inside constructor
现在我已经在构造函数中成功创建了一个线程,我知道它必须加入。在我开发API时,我无法控制主函数,所以我无法在那里加入它。
在类析构函数中加入线程是否正确,考虑到该类的实例化对象将具有应用程序的生命周期?
答案 0 :(得分:3)
你可以这样做。但是,您是否真的对启动新线程的机制感兴趣,或者您是否对异步执行某些内容的效果感兴趣?如果是后者,您可以转到更高级async
机制:
#include <iostream>
#include <future>
void bar()
{
std::cout << "I'm bar" << std::endl;
}
class foo
{
public:
foo() :
m_f(std::async(
std::launch::async,
bar))
{
}
~foo()
{
m_f.get();
}
private:
std::future<void> m_f;
};
int main ()
{
foo f;
}
您在构造函数中要求异步启动bar
。你不在乎自己管理线程 - 让库处理它。
将结果future
放入会员。
在dtor中,get
未来。
答案 1 :(得分:1)
当然,你可以做到。只要确保线程存在,否则你的程序将永远挂在该连接上。
答案 2 :(得分:1)
我已经提出了一个线程模式,我已经找到它处理C ++中关于在类中运行线程的所有奇怪情况。
答案 3 :(得分:1)
您遇到了C ++ RAII的一个缺点:析构函数无法轻松报告错误,并且析构函数不能正常失败,因为它们没有返回值,抛出异常是bad idea。
因此,如果另一个线程没有响应停止请求,那么析构函数可以做什么?它可以等待更多或猛烈地破坏其他线程或让它继续运行,这些都不是很好的选择。然后它可以忽略这种情况,只是记录它,或者抛出一个异常,尽管应用程序立即终止的风险,再次不是一个非常好的选项集。
所以,你至少有3个选择
对于线程,线程未能及时终止通常可以被认为是与段错误相当的编程错误,因此您可以选择使用有用的(对开发人员)诊断消息(上面的第2个要点)终止应用程序,或者只是让程序挂起(上面的第1个要点)。但这有点风险,因为如果你需要创建一个无法快速终止的线程(它正在进行阻塞系统调用,或者它必须通知网络连接的另一端,这可能很慢)在锁定设计之前考虑如何解决这个问题是个好主意。