About this->moveToThread(this)——QtWidgets

Preface

There are two official ways to use QThread: one is to subclass QThread and reimplement run; the other is to use QObject::MoveToThread to communicate in different threads through signal slots.

Recently I saw a way of writing, which is to fuse the two to subclass QThread, and then this->moveToThread(this). I find it strange, but I can't say it's wrong. I wrote a demo myself and tested it. It works, but there are a lot of things that need to be paid attention to.

illustrate

I have tried several situations. Different situations require different things to pay attention to.

No reimplementation of run

Just subclass QThread (if the class name is MyThread), do not reimplement run, and perform moveToThread in the constructor or elsewhere. In this case, use the QueueConnection of the signal slot to connect, and the slot function in MyThread is executed in the child thread.


//----------------------------.h文件----------------------------
#include<QThread>

class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = Q_NULLPTR);
    ~ MyThread() ;

public slots:
    void sayHello();

};


//----------------------------.cpp文件----------------------------

MyThread::MyThread(QObject *parent)
    :QThread(parent)
{
    this->moveToThread(this);
}

void MyThread::sayHello()
{
    qDebug()<<__FUNCDNAME__<<QThread::currentThreadId();
}

Call in the main interface

    connect(ui->pushButton,SIGNAL(clicked(bool)),this,SIGNAL(say()));
    connect(this,SIGNAL(say()),&m_thread,SLOT(sayHello()),Qt::QueuedConnection);

    m_thread.start();

Click the button and you can see the print as follows

Conclusion : Through the above practice, we can see that this method is feasible. The main thread sends a signal and executes it in the child thread.

Analysis : Run is not implemented, which means that QThread::start() calls the run of QThread itself, that is, the event loop is started in the child thread, and the two threads communicate through the signal slot. There is nothing wrong with this.

QThreads begin executing in run(). By default, run() starts the event loop by calling exec() and runs a Qt event loop inside the thread

Reimplement run

Call exec()

Reimplement run and call exec() in run. This usage is almost the same as above, except that you can execute some code before calling exec(). Of course, the executed code is also executed in the child thread.

void MyThread::run()
{
    qDebug()<< "Entering thread";
    {

        //to do something
        sayHello();

        // Start the event loop.
        qDebug() << "Event loop starting";
        exec();
        qDebug() << "Event loop stopped";
    }
    qDebug() << "Exiting thread";

}

Looking at the print, you can see the entire execution process:

 

Conclusion : It works! 

exec() is not called

exec() is not executed, that is, the event loop is not started in the child thread.

void MyThread::run()
{
    sayHello();
}

Result : Signal slots are not feasible unless the connection method is changed to direct Qt::DirectConnection, that is, the slot function is executed in the main thread or other threads.

Conclusion : In this usage method, only the run function is executed in the sub-thread. Even if this->moveToThread(this) is used, other functions in this class cannot be executed in the sub-thread through the signal slot. The same is true. , QMetaObject::invokeMethod using the queue connection method will not work, that is, it will not work as long as it relies on the event loop in the child thread.

Note : QTimer defined outside run cannot be started in run.

Guess you like

Origin blog.csdn.net/xiaopei_yan/article/details/130752622