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

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


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

只有调用了QThread::start()后,子线程才是真正的启动,并且只有在run()函数才处于子线程内。

(3)我们再试一下点击【stop】按钮,然后检查线程的状态:

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

点击【stop】按钮使 m_flag = false, 此时run函数也就可以跳出死循环,并且停止了线程的运作,之后我们就不能再次使用该线程了,也许有的人说,我再一次start不就好了吗?再一次start已经不是你刚才使用的线程了,这是start的是一个全新的线程。到此子类化 QThread ,不使用事件循环的线程使用就实现了,就这么简单。

三、使用事件循环实例

run函数中的 while 或者 for 循环执行完之后,如果还想让线程保持运作,后期继续使用,那应该怎么做?
可以启动子线程的事件循环,并且使用信号槽的方式继续使用子线程。注意:一定要使用信号槽的方式,否则函数依旧是在创建QThread对象的线程执行。

在run函数中添加QThread::exec()来启动事件循环。(注意: 在没退出事件循环时,QThread::exec()后面的语句都无法被执行,退出后程序会继续执行其后面的语句);

为QThread子类定义信号和槽;

在QThread子类构造函数中调用 moveToThread(this)(注意: 可以实现构造函数在子线程内执行,但此方法不推荐,更好的方法会在后期的文章进行介绍)。

接着上述的实例,在InheritQThread类构造函数中添加并且调用moveToThread(this);在run函数中添加exec();并定义槽函数:

/**************在InheritQThread构造函数添加moveToThread(this)**********/ InheritQThread(QObject *parent = Q_NULLPTR):QThread(parent){ moveToThread(this); } /**************在InheritQThread::run函数添加exec()***************/ 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(); //开启事件循环 } /************在InheritQThread类中添加QdebugSlot()槽函数***************/ public slots: void QdebugSlot(){ qDebug()<<"QdebugSlot function is in thread:"<<QThread::currentThreadId(); }

在MainWindow类中添加QdebugSignal信号;在构造函数中将QdebugSignal信号与InheritQThread::QdebugSlot槽函数进行绑;添加一个发送QdebugSignal信号的按钮:

/**********在MainWindow构造函数中绑定信号槽******************/ explicit MainWindow(QWidget *parent = nullptr) : QMainWindow(parent), ui(new Ui::MainWindow){ qDebug()<<"GUI thread = "<<QThread::currentThreadId(); ui->setupUi(this); WorkerTh = new InheritQThread(this); connect(WorkerTh, &InheritQThread::ValueChanged, this, &MainWindow::setValue); connect(this, &MainWindow::QdebugSignal, WorkerTh, &InheritQThread::QdebugSlot); //绑定信号槽 } /********MainWindow类中添加信号QdebugSignal槽以及按钮事件槽函数**********/ signals: void QdebugSignal(); //添加QdebugSignal信号 private slots: //按钮的事件槽函数 void on_SendQdebugSignalBt_clicked() { emit QdebugSignal(); }

实现事件循环的程序已修改完成,来看下效果:

(1)在运行的时候为什么会出现以下警告?

QObject::moveToThread: Cannot move objects with a parent

我们看到MainWindow类中是这样定义InheritQThread类对象的:WorkerTh = new InheritQThread(this)。如果需要使用moveToThread()来改变对象的依附性,其创建时不能够带有父类。将语句改为:WorkerTh = new InheritQThread()即可。

(2)修改完成后,点击【start】启动线程,然后点击【stop】按钮跳出run函数中的while循环,最后点击【check thread state】按钮来检查线程的状态,会是什么样的情况呢?

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

由上图可以看到,线程依旧处于运行状态,这是因为run函数中调用了exec(),此时线程正处于事件循环中。

(3)接下来再点击【Send QdebugSignal】按钮来发送QdebugSignal信号。

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

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