【QT】子类化QThread实现多线程 (3)

【QT】子类化QThread实现多线程

由终端的打印信息得知,InheritQThread::QdebugSlot槽函数是在子线程中执行的。

四、子类化QThread线程的信号与槽

【QT】子类化QThread实现多线程

从上图可知,事件循环是一个无止尽循环,事件循环结束之前,exec()函数后的语句无法得到执行。只有槽函数所在线程开启了事件循环,它才能在对应信号发射后被调用。无论事件循环是否开启,信号发送后会直接进入槽函数所依附的线程的事件队列,然而,只有开启了事件循环,对应的槽函数才会在线程中得到调用。下面通过几种情况来验证下:

(1)代码和《三、使用事件循环》小节的代码一样,然后进行如下的操作:点击【start】按钮->再点击【Send QdebugSignal】按钮,这个时候槽函数会不会被执行呢?

【QT】子类化QThread实现多线程


【QT】子类化QThread实现多线程

这种情况无论点多少次发送QdebugSignal信号,InheritQThread::QdebugSlot槽函数都不会执行。因为当前线程还处于while循环当中,如果需要实现槽函数在当前线程中执行,那么当前线程就应该处于事件循环的状态,也就是正在执行exec()函数。所以如果需要InheritQThread::QdebugSlot槽函数执行,就需要点击【stop】按钮退出while循环,让线程进入事件循环。

(2)在《三、使用事件循环》小节的代码基础上,把InheritQThread::run函数删除,然后进行如下的操作:点击【start】启动线程->点击【stop】按钮跳出run函数中的while循环进入事件循环->点击【Send QdebugSignal】按钮来发送QdebugSignal信号,会有什么结果呢?

结果会和上面第一种情况一样,虽然信号已经在子线程的事件队列上,但是由于子线程没有事件循环,所以槽函数永远都不会被执行。

(3)在上面《三、使用事件循环》小节的代码基础上,将InheritQThread构造函数中的 moveToThread(this) 去除掉。进行如下操作:点击【start】启动线程->点击【stop】按钮跳出run函数中的while循环进入事件循环->点击【Send QdebugSignal】按钮来发送QdebugSignal信号,会有什么结果呢?

【QT】子类化QThread实现多线程

由上图可以看出InheritQThread::QdebugSlot槽函数居然是在GUI主线程中执行了。因为InheritQThread对象我们是在主线程中new出来的,如果不使用moveToThread(this)来改变对象的依附性关系,那么InheritQThread对象就是属于GUI主线程,根据connect信号槽的执行规则,最终槽函数会在对象所依赖的线程中执行。信号与槽绑定的connect函数的细节会在后期的《跨线程的信号槽》文章进行单独介绍。

五、如何正确退出线程并释放资源

InheritQThread类的代码不变动,和上述的代码一样:

#ifndef INHERITQTHREAD_H #define INHERITQTHREAD_H #include <QThread> #include <QMutex> #include <QMutexLocker> #include <QDebug> class InheritQThread:public QThread { Q_OBJECT public: InheritQThread(QObject *parent = Q_NULLPTR):QThread(parent){ moveToThread(this); } void StopThread(){ QMutexLocker lock(&m_lock); m_flag = false; } protected: //线程执行函数 void run(){ qDebug()<<"child thread = "<<QThread::currentThreadId(); int i=0; m_flag = true; while(1) { ++i; emit ValueChanged(i); QThread::sleep(1); { QMutexLocker lock(&m_lock); if( !m_flag ) break; } } exec(); } signals: void ValueChanged(int i); public slots: void QdebugSlot(){ qDebug()<<"QdebugSlot function is in thread:"<<QThread::currentThreadId(); } public: bool m_flag; QMutex m_lock; }; #endif // INHERITQTHREAD_H

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdfzd.html