24

My aim is to keep an std::thread object as data member, and initialize it when needed.
I'm not able to do this (as in my code below) because the copy constructor of the std::thread class is deleted. Is there any other way to do it?

class MyClass
{
    public:
        MyClass():DiskJobThread(){};
        ~MyClass();

        void DoDiskJobThread();

    private:
        int CopyThread(const std::wstring & Source, const std::wstring & Target);
        int MoveThread(const std::wstring & Source, const std::wstring & Target);
        std::thread DiskJobThread;
};

MyClass::~MyClass()
{
    DiskJobThread.join();
}

void MyClass::DoDiskJobThread()
{
    std::wstring Source = GetSource();
    std::wstring Target = GetTarget();
    int m_OperationType = GetOperationType();
    if      (m_OperationType == OPERATION_COPY)
    {
        DiskJobThread = std::thread(&MyClass::CopyThread, *this, Source, Target);
    }
    else if (m_OperationType == OPERATION_MOVE)
    {
        DiskJobThread = std::thread(&MyClass::MoveThread, *this, Source, Target);
    }
}
4

4 回答 4

15

将它包装在指针中怎么样?

std::unique_ptr<std::thread> thread_ptr;

// Look into std::make_unique if possible
thread_ptr = std::unique_ptr<std::thread>(new std::thread(...));

编辑:是的,其他人已经提到了它,我觉得没有必要在这里添加它,但为了避免更多的反对意见堆积,我会说:你正在传递*this,而不是this因此复制你的类的实例. (出现问题是因为它是不可复制的。通过this,你应该很高兴。)

于 2013-08-22T09:10:12.920 回答
11

线程对象创建后不能初始化;根据定义,初始化发生在创建对象时。但是您可以使用swap将线程对象移动到另一个对象中:

std::thread thr1; // no thread of execution
std::thread thr2(my_function_object); // creates thread of execution
thr1.swap(thr2);  // thr1 is now running the thread created as thr2
                  // and thr2 has no thread of execution
于 2013-08-22T13:06:05.240 回答
11

您的问题是其他问题-您将实例传递MyClass给线程,而不是MyClass成员函数期望的指针。像这样简单地改变DoDiskJobThread()(不要取消引用this):

void MyClass::DoDiskJobThread()
{
    std::wstring Source = GetSource();
    std::wstring Target = GetTarget();
    int m_OperationType = GetOperationType();
    if      (m_OperationType == OPERATION_COPY)
    {
        DiskJobThread = std::thread(&MyClass::CopyThread, this, Source, Target);
    }
    else if (m_OperationType == OPERATION_MOVE)
    {
        DiskJobThread = std::thread(&MyClass::MoveThread, this, Source, Target);
    }
}

您收到错误是因为*this尝试复制MyClass到线程函数中,并且您的类的复制 ctor 被删除(因为std::thread被删除了)。但是,无论如何,成员函数CopyThreadMoveThread需要一个指针作为第一个(隐藏)参数。

现场演示

于 2013-08-22T09:19:35.020 回答
1

我的目标是将std::thread对象保留为数据成员,并在需要时对其进行初始化。

由于默认构造的std::thread对象没有关联的执行线程,因此您可以通过使用这样的对象作为(移动)赋值操作的目标来实现这一点。但是,请注意以下不是初始化,而是赋值

std::thread th; // no thread of execution associated with th object
// ...
th = std::thread(func);

创建的临时std::thread对象std::thread(func)有一个关联的执行线程。这个执行线程的所有权是th通过移动分配转移到的——即,th从临时线程中窃取该执行线程的所有权。

请注意,如果th在分配时有关联的执行线程,std::terminate()则将被调用。

于 2020-06-11T22:28:26.653 回答