堆栈上的c ++ std :: thread

时间:2015-01-28 19:26:51

标签: c++ multithreading c++11

我有一个普通构造函数的对象。构造函数有很多初始化要做。大部分初始化都可以异步执行,所以我从构造函数中调用一个新线程。

当线程在堆栈上初始化时,看起来线程在构造函数退出时被破坏而导致崩溃。这看起来像这样:

class MyObject
{
    MyObject()
    {
        // Typical initialization
        // ...

        // Time consuming initialization
        std::thread(&MyObject::Init; this); // Create new thread to call Init();

        // Crash when exit MyObject() here
    }

    void Init()
    {
         // Time consuming operations
    }
};

替代方法(可行)是在堆上创建线程。

class MyObject
{
    std::thread* StartupThread;

    MyObject()
    {
        // Typical initialization
        // ...

        // Time consuming initialization
        StartupThread = new std::thread(&MyObject::Init; this); // Create new thread to call Init();

        // Crash when exit MyObject() here
    }
    ~MyObject()
    {
        StartupThread->join();
        delete StartupThread;
    }

    void Init()
    {
         // Time consuming operations
    }

};

我的问题

是否有任何伤害是离开未加入的&未使用的线程对象在对象的生命周期内是活着的,还是应该在Init()完成后立即尝试清理它?

有没有办法在线程完成时“自动”处理线程,这样它就不会留下来?

基本上,我可以以某种方式获取堆栈中的线程而不会像我描述的那样崩溃吗?

2 个答案:

答案 0 :(得分:3)

怎么样:

class MyObject
{
    MyObject ()
    {
        f = std::async (std::launch::async, &MyObject::Init, this);
    }

private:
    void Init ();
    std::future<void> f;
};

这使您可以在要同步任务时执行f.get ()。如果析构函数是对象的最后一个活动副本,则它将自动连接(如果您不希望出现此行为,则可能需要删除复制构造函数。)

请注意,您希望在销毁之前的某个时刻进行同步,因为如果Init抛出异常,您的析构函数将会。

另外,如果您想要detach路线,请参阅this

答案 1 :(得分:0)

您可以从堆栈中调用std::thread::detach(),但这是非常危险,因为该对象可能会在其仍在运行时被删除。

根据您的要求,最好的选择是确保它在Init()和解构函数的末尾加入。 我认为更好的设计是为了简单起见,在构造函数的末尾为join()假设一旦启动线程并且{{1}时没有其他处理要做调用,这将是最好的选择。