Qt多线程
我们之前的程序都是单线程运行,接下来我们开始引入多线程。就相当于以前的一个人在工作,现在多个人一起工作。
Qt中非常有必要使用多线程,这是因为,Qt应用是事件驱动型的,一旦某个事件处理函数处理时间过久,就会造成其它的事件得不到及时处理。
Qt中使用QThread来管理线程,一个QThread对象,就是一个线程。QThread对象也有消息循序exec()函数,用来处理自己这个线程的事件。
Qt实现多线程有两种方式
1、Qt第一种创建线程方式
首先要继承QThread
重写虚函数QThread::run
[virtual protected] void QThread::run() /* * 基类QThread的run函数只是简单启动exec()消息循环 */
例如:
#include <QApplication> #include <QThread> #include <QDebug> class MyThread : public QThread { public: void run() { qDebug() << "QThread begin" << endl; qDebug() << "child thread" << QThread::currentThreadId() << endl; QThread::sleep(5); qDebug() << "QThread end" << endl; exec(); } }; int main(int argc, char** argv) { QApplication app(argc, argv); MyThread thread; thread.start(); qDebug() << "main thread" << QThread::currentThreadId() << endl; QThread::sleep(5); qDebug() << "main thread" << QThread::currentThreadId() << endl; thread.quit(); qDebug() << "main thread thread.quit()" << endl; tread.wait(); qDebug() << "main thread thread.wait()" << endl; return app.exec(); }
使用QThread的quit可以退出线程的消息循环,有时候不是马上退出,需要等到cpu的控制权交还给线程的exec()。
一般在子线程退出的时候需要主线程去回收资源,可以调用QThread的wait,等待子线程的退出,然后回收资源.
2、Qt第二种创建线程方式
继承 QObject
实例化一个QThread对象
实现槽函数.
QObject子类对象通过moveToThread将自己放到线程QThread对象中.
调用QThread对象的start函数启动线程
必须通过发射信号来让槽函数在线程中执行,发射的信号存放在线程exec()消息队列中。
例如:
mywork.h
#ifndef MYWORK_H #define MYWORK_H #include <QThread> #include <QDebug> class MyWork : public QObject { Q_OBJECT public slots: void workSlot() { qDebug() << "QThread begin" << endl; qDebug() << "child thread" << QThread::currentThreadId() << endl; QThread::sleep(5); qDebug() << "QThread end" << endl; } }; #endif // MYWORK_H
widget.cpp
#include <QApplication> #include <QThread> #include <QDebug> #include "mywork.h" int main(int argc, char** argv) { qDebug() << "main thread" << QThread::currentThreadId() << endl; QApplication app(argc, argv); QThread thread; MyWork work; work.moveToThread(&thread); QObject::connect(&thread, SIGNAL(started()), &work, SLOT(workSlot())); thread.start(); QThread::sleep(6); qDebug() << "thread is runing" << thread.isRunning() << endl; thread.quit(); //调用quit让线程退出消息循环,否则线程一直在exec循环中 thread.wait(); //调用完quit后紧接着要调用wait来回收线程资源 qDebug() << "thread is runing" << thread.isRunning() << endl; return app.exec(); }
需要特别注意的是:
- 线槽函数已经执行完进入线程exec()中,可以通过发射信号重新让槽函数在线程中执行。也可以通过quit()退出线程exec()。
- QObject派生类对象,将要调用moveToThread,不能指定一个主线程父对象托管内存。
- QWidget的对象及派生类对象都只能在GUI主线程运行,不能使用moveToThread移到子线程中,即使没有指定父对象。
多线程对象内存释放
既然QObject对象无法托管内存对象,那么到底是先释放线程对象,还是先释放这个QObject对象?
先把QObject在线程循环中释放(使用QObject::deleteLater函数),然后QThread::quit,然后QThread::wait。
例如:
mywork.h
#ifndef MYWORK_H #define MYWORK_H #include <QThread> #include <QDebug> class MyWork : public QObject { Q_OBJECT public: ~MyWork() { qDebug() << __FUNCTION__ << endl; } public slots: void workSlot() { while(1) { qDebug() << "Work begin" << endl; QThread::sleep(5); qDebug() << "work end" << endl; } } void otherWorkSlot() { qDebug() << "otherWork begin" << endl; QThread::sleep(5); qDebug() << "otherWork end" << endl; } }; #endif // MYWORK_H
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/484372.html