Points to note for movetoThread applications

analyze

Description of the official website:

void QObject::moveToThread(QThread *targetThread)

Changes the thread affinity for this object and its children. The
object cannot be moved if it has a parent. Event processing will
continue in the targetThread.

To move an object to the main thread, use QApplication::instance() to
retrieve a pointer to the current application, and then use
QApplication::thread() to retrieve the thread in which the application
lives. For example:

myObject->moveToThread(QApplication::instance()->thread());

If targetThread is zero, all event processing for this object and its
children stops.

Note that all active timers for the object will be reset. The timers
are first stopped in the current thread and restarted (with the same
interval) in the targetThread. As a result, constantly moving an
object between threads can postpone timer events indefinitely.

A QEvent::ThreadChange event is sent to this object just before the
thread affinity is changed. You can handle this event to perform any
special processing. Note that any new events that are posted to this
object will be handled in the targetThread.

Warning: This function is not thread-safe; the current thread must be
same as the current thread affinity. In other words, this function can
only “push” an object from the current thread to another thread, it
cannot “pull” an object from any arbitrary thread to the current
thread.

One of the key words:

Changes the thread affinity for this object and its children. The
object cannot be moved if it has a parent. Event processing will
continue in the targetThread.

The understanding of this sentence:
1. The constructor of the object can not only use the parent class, but also other things of the parent class.
2. Changing the association of threads is aimed at the object and its children, but if it is not the new of the child, it will not work. of

Example 1

Change the association of the thread, for the object and its children, but if it is not the new of the children, it will not work.
As shown below:
insert image description here

The single new variable in the object cannot be moved to the target thread, unless it is a child node.
The code of the controller:

#include "controller.h"

Controller::Controller(QObject *parent) : QObject(parent)
{
    
    
  QString name = "thread1";
  Worker *worker = new Worker(name);
  m_pWorkerThread = new QThread();
  worker->moveToThread(m_pWorkerThread);
  connect(m_pWorkerThread, &QThread::finished, worker, &QObject::deleteLater);
  connect(this, &Controller::operate, worker, &Worker::doWork);
   connect(this, &Controller::signalsBegin, worker, &Worker::onBegin);
  connect(worker, &Worker::resultReady, this, &Controller::handleResults);
  m_pWorkerThread->start();
}

Controller::~Controller()
{
    
    
  m_pWorkerThread->quit();
  m_pWorkerThread->wait();
}

void Controller::beginOperate()
{
    
    
    QString str = "begin";
    emit operate(str);
}

void Controller::begin()
{
    
    
    emit signalsBegin();
}

void Controller::handleResults(const QString &str)
{
    
    
   qDebug("enter function Controller::handleResults str=%s", str.toStdString().c_str());
   QThread *currentThread = QThread::currentThread();
   qDebug("exit function Controller::handleResults currentThread=%p", currentThread);
}

The code of the worker class:

Worker::Worker(QString name, QObject *parent) : QObject(parent)
{
    
    
   qDebug("name=%s", name.toStdString().c_str());
   m_name = name;
   m_pTimer = new QTimer();
   m_pTimer->setInterval(1000);
}

void Worker::doWork(const QString &parameter)
{
    
    
 qDebug("enter function Worker::doWork parameter=%s", parameter.toStdString().c_str());
 QString result;
 /* ... here is the expensive or blocking operation ... */
 result = "executing";
 emit resultReady(result);
 QThread *currentThread = QThread::currentThread();
 qDebug("exit function Worker::doWork currentThread=%p", currentThread);
}

void Worker::onBegin()
{
    
    
    m_pTimer->start();
}

main function:

#include <QCoreApplication>
#include "controller.h"
int main(int argc, char *argv[])
{
    
    
    QCoreApplication a(argc, argv);
    Controller *controller = new Controller();
    controller->beginOperate();
    controller->begin();
    return a.exec();
}

The above problem is:
the problem caused by the sentence controller->begin(), which calls: m_pTimer->start();
and the member variable m_pTimer is created in the main thread, not in the child thread, so the report wrong above.
It can be seen that the movetoThread() function only moves non-new member variables and sub-objects, that is, the new variable of non-sub-objects is not moved.
Code changes like this will do the trick:

Worker::Worker(QString name, QObject *parent) : QObject(parent)
{
    
    
   qDebug("name=%s", name.toStdString().c_str());
   m_name = name;
   m_pTimer = new QTimer(this);
   m_pTimer->setInterval(1000);
}

That is, QTimer() is changed to QTimer(this);

Summarize

How to say this thing? The movetoThread() function only moves the non-new member variables and sub-objects, that is, the non-sub-object new variables are not moved. Variables in QT cannot cross threads, so cross-thread variables will report errors, and some report: Cannot
create children for a parent that is in a different thread.
This error does not need to add this, because this is the this of the main thread, and removing this can solve the problem.
QObject::startTimer: Timers cannot be started from another thread
This is an error, you need to add this, because this is the this of the target thread, adding this, Timers is also moved to the target thread, so it is in one thread.
The essence is the same, that is, when the variable cross-thread (parent and child cross-thread is not allowed, the essence is also variable cross-thread)
without moveToThread:

insert image description here

After moveToThread is like this:
insert image description here

Guess you like

Origin blog.csdn.net/maokexu123/article/details/131225817
Recommended