关于this->moveToThread(this)——QtWidgets

前言

官方关于QThread的用法有两种:一是子类QThread,并重新实现run;二是使用QObject::MoveToThread,通过信号槽在不同的线程内通信。

最近看到了一种写法,就是将两者融合就是子类QThread,然后this->moveToThread(this)。觉得很奇怪,但是也不能说有错,自己写demo测了一下,能用,就是需要注意的东西挺多。

说明

尝试了几种情况,不同情况,需要注意的东西不一样。

不重新实现run

只是子类QThread(假如类名为MyThread),不重新实现run,在构造函数或者其他地方进行moveToThread。这种情况,使用信号槽的QueueConnection进行连接,MyThread里的槽函数是在子线程中执行的。


//----------------------------.h文件----------------------------
#include

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__<

在主界面调用

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

    m_thread.start();

点击按钮,可看到打印如下

结论:通过以上实践,可以看到此方式是可行的,主线程发送信号,在子线程中执行。

分析:不实现run,也就是说QThread::start() 的时候调用的是QThread本身的run,也就是在子线程启动了事件循环,两线程通过信号槽通信,这没毛病。

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

重新实现run

调用exec()

重新实现run,并且在run里调用exec(),此使用跟上面的几乎一样,只是可以在调用exec()前,执行一些代码,当然执行的代码也是子线程中执行的。

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";

}

看打印,可以看出整个执行流程:

 关于this->moveToThread(this)——QtWidgets_第1张图片

结论:可行! 

不调用exec()

不执行exec(),即在子线程中不启动事件循环。

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

结果:信号槽不可行的,除非将连接方式改为直连Qt::DirectConnection,也就是在主线程或者其他线程中执行槽函数。

结论:此种使用方法,只有run函数的在子线程中执行,即使使用this->moveToThread(this),也是不能通过信号槽的方式,让此类中的其他函数在子线程中执行,同理,QMetaObject::invokeMethod使用队列连接方式的也不行,也就是只要依赖子线程里的事件循环的都不行。

注意:在run外定义的QTimer是无法是在run里启动的。

你可能感兴趣的:(qt,开发语言)