使用析构函数进行线程连接

时间:2015-06-19 06:41:52

标签: c++ multithreading destructor

这是我的问题的延续:Thread creation inside constructor

现在我已经在构造函数中成功创建了一个线程,我知道它必须加入。在我开发API时,我无法控制主函数,所以我无法在那里加入它。

在类析构函数中加入线程是否正确,考虑到该类的实例化对象将具有应用程序的生命周期?

4 个答案:

答案 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 ++中关于在类中运行线程的所有奇怪情况。

http://blog.chrisd.info/how-to-run-threads/

答案 3 :(得分:1)

您遇到了C ++ RAII的一个缺点:析构函数无法轻松报告错误,并且析构函数不能正常失败,因为它们没有返回值,抛出异常是bad idea

因此,如果另一个线程没有响应停止请求,那么析构函数可以做什么?它可以等待更多或猛烈地破坏其他线程或让它继续运行,这些都不是很好的选择。然后它可以忽略这种情况,只是记录它,或者抛出一个异常,尽管应用程序立即终止的风险,再次不是一个非常好的选项集。

所以,你至少有3个选择

  • 已知连接线程表现良好,因此您知道它会在请求时立即终止,并且加入析构函数是安全的。风险是,如果线程没有终止,程序将挂起连接。
  • 您确定析构函数中可用的错误处理选项(如上所述)已足够,并且在析构函数中加入即可。您必须将错误检测和处理代码添加到析构函数(例如超时)。
  • 提供单独的“close”方法,该方法可能需要超时参数,然后返回错误值或在失败时抛出异常。

对于线程,线程未能及时终止通常可以被认为是与段错误相当的编程错误,因此您可以选择使用有用的(对开发人员)诊断消息(上面的第2个要点)终止应用程序,或者只是让程序挂起(上面的第1个要点)。但这有点风险,因为如果你需要创建一个无法快速终止的线程(它正在进行阻塞系统调用,或者它必须通知网络连接的另一端,这可能很慢)在锁定设计之前考虑如何解决这个问题是个好主意。