QThread - 使用moveToThread将类成员移动到线程中

3
我将从多线程开始,但在将对象移动到QThread时遇到了一些问题。我的Controller类实例化Worker,为Worker创建必要的线程并将Worker移动到新线程中。当worker线程启动时,会在worker上进行计算。Worker类包含一个Dummy对象,在worker计算期间使用(函数DoDummyStuff())。一切似乎都运行正常,除了DoDummyStuff()似乎在主(控制器)线程而不是工作线程中执行。这是因为Worker对象(因此是Dummy对象)最初是在主线程中创建的吗?有没有办法将Worker对象的所有类成员移动到worker线程中?
这里是代码片段:
Controller.h
class Controller: public QObject
{
    Q_OBJECT

public:
    Controller(std::vector<double> _data, QString _fn);
    void startControl();

private:
    QThread workerThread_;
    Worker worker_;
    PostProcessing postProc_;

};

Controller.cpp

Controller::Controller(std::vector<double> _data, QString _fn): QObject(), workerThread_(), worker_(_data), postProc_()
{
    QObject::connect(&workerThread_, SIGNAL(started()), &worker_, SLOT(doWork()));
    QObject::connect(&worker_, SIGNAL(signalResultReady(double)), &postProc_, SLOT(update(double)));
}

void Controller::startControl()
{
    worker_.moveToThread(&workerThread_);
    workerThread_.start();
}

Worker.h

class Worker: public QObject
{
    Q_OBJECT

public:
    Worker(std::vector<double> _coord);

signals:
    void signalResultReady(double);

public slots:
    void doWork();

private:
    double res_;
    std::vector<double> coord_;
    Dummy dummyCreatedInWorker_;
};

Worker.cpp

Worker::Worker(std::vector<double> _coord): QObject(), res_(0), coord_(_coord), dummyCreatedInWorker_()
{
}

void Worker::doWork()
{
    qDebug() << "Worker thread ID" << this->thread();
    for(unsigned int ii = 0; ii < coord_.size(); ii++)
    {
        res_ += coord_[ii];
        dummyCreatedInWorker_.doDummyStuff();
        emit signalResultReady(res_);

        /* ....*/
    }
}

Dummy::doDummyStuff

void Dummy::doDummyStuff()
{
    qDebug() << "Doing dummy stuff from thread" << this->thread();
    for(int ii = 0; ii < 10; ii++)
    {
        res_ += ii;
    }
}

doWork() 中的调试是否显示了正确的线程?您直接从 doWork() 调用 doDummyStuff(),因此它将在与 doWork() 相同的线程中执行,独立于任何 QObject 线程亲和性。 - Frank Osterfeld
是的,在doWork()中我得到了正确的线程ID。正如BeniBela所指出的那样,我在doDummyStuff()中误用了this->thread。使用QThread::currentThread()可以返回正确的线程ID。感谢您的回答! - Eph
如果 this->thread() 不等于 QThread::currentThread(),那么你很可能在面对代码中的一个错误,除非你已经明确设计了你的 QObject 可以从多个线程访问,并且被调用的方法具有适当的同步保护来访问对象的数据。 - Kuba hasn't forgotten Monica
1个回答

3

你的虚拟类也是从QObject派生的吗?

如果你将虚拟类设置为worker的子项,那么当你调用moveToThread时,它将自动移动。

即,如果它没有隐藏默认的QObject构造函数,将worker传递给虚拟类的构造函数:

Worker::Worker(std::vector<double> _coord): 
  QObject(), res_(0), coord_(_coord), dummyCreatedInWorker_(this)

或者,您可以在工作线程和虚拟对象上使用moveToThread进行调用。


然而,即使不改变任何内容,Dummy::doDummyStuff()也会在工作线程中被调用。

调用任何东西都不会改变线程,只有发射(排队)信号才会改变。

但是,您不能使用this->thread()来检查方法所在的线程。它返回对象“所在”的线程,即如果对像通过信号被调用了,那么对象的(排队)槽将在其中调用的线程。

相反,使用QThread::currentThread()来查看调用方法的线程。

您可以在任何线程中调用任何对象的任何方法,这完全独立于对象和线程之间的关联。


确实,使用 QThread::currentThread() 返回正确的线程 ID。感谢澄清! - Eph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接