Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QThread - Move class member to thread using moveToThread

I'm starting with multithreading and have some troubles moving objects to a QThread. My Controller class instanciates the Worker, creates the necessary thread for the Worker and move the Worker to the new thread. Computation on the worker starts when the worker thread is started. The Worker class contains a Dummy object, which is used during the worker calculation (function Dummy::doDummyStuff()). Everything seems to work fine, except that doDummyStuff() seems to be executed in the main (controller) thread instead of the worker thread. Is this because the Worker object (and hence the Dummy object) was created first in the main thread ? Is there a way to move all class members of the Worker object in the worker thread ?

Here is a code snippet :

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;
    }
}
like image 939
Eph Avatar asked Jul 25 '26 19:07

Eph


1 Answers

Your dummy class is also derived from QObject?

If you set the dummy to be an child of the worker, then it will automatically be moved when you call moveToThread.

i.e. pass the worker to the constructor of the dummy, if it did not hide the default qobject constructor:

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

Alternatively, you can call moveToThread on the worker and the dummy.


However, even without changing anything, Dummy::doDummyStuff() is called in the worker thread.

Calling anything does not change the thread, only emitting (queued) signals.

But you cannot use this->thread() to check in which thread the method is called. It returns the thread the object "lives in", i.e. the thread in which (queued) slots of the object would be called, if the are invoked by a signal.

Instead use QThread::currentThread() to see the thread a method was called in.

You can call any method of any object in any thread, it is completely independent of the associations between objects and threads

like image 154
BeniBela Avatar answered Jul 27 '26 13:07

BeniBela



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!