12.QT线程的两种启动方式

it2025-03-06  28

一、QT中的线程

QT中的线程主要是通过QThread进行管理,一个QThread对象管理程序中的一个线程。 QThreads管理的线程在run()中开始执行。 默认情况下,run()通过调用exec()启动并在线程中运行事件循环。

线程的启动方式有两种:

1.使用moveToThread启动线程

示例

//头文件 #ifndef THREADSTART_H #define THREADSTART_H #include <QObject> #include <QThread> #include <iostream> #include <cassert> using namespace std; class work : public QObject { Q_OBJECT public: explicit work(QObject *parent = nullptr); virtual ~work(); public slots: void dowork(); signals: void emitsignal(); }; class control:public QObject { Q_OBJECT public: explicit control(QObject *parent=nullptr); virtual ~control(); public slots: void signalhandler(); signals: void worksignal(); private: QThread workthread_; }; #endif // THREADSTART_H //源文件 #include "threadstart.h" work::work(QObject *parent) : QObject(parent) { cout<<__func__<<endl; } work::~work() { cout<<__func__<<endl; } void work::dowork() { while(1) { QThread::sleep(1); cout<<__func__<<QThread::currentThreadId()<<endl; emit emitsignal(); } } control::control(QObject *parent):QObject(parent) { work *pwork=new work(); pwork->moveToThread(&workthread_);//将pwork指向的对象移动到目标线程workthread_中 connect(&workthread_, &QThread::finished, pwork, &QObject::deleteLater); connect(this, &control::worksignal, pwork, &work::dowork); connect(pwork, &work::emitsignal, this, &control::signalhandler); workthread_.start();//start内部会调用run函数启动一个线程,如果不重新run函数,run函数默认执行exec emit worksignal(); } control::~control() { cout<<__func__<<endl; workthread_.quit(); workthread_.wait(); } void control::signalhandler() { cout<<__func__<<QThread::currentThreadId()<<endl; cout<<"received signal"<<endl; } //主函数 #include <QCoreApplication> #include "threadstart.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); cout<<QThread::currentThreadId()<<endl; control cl; return a.exec(); }

上述程序输出结果如下

上述代码的思路就是在主线程中创建一个QThread对象,然后将工作函数放在该QThread对象对象中去执行,当主线程发出worksignal时,会调用工作线程中的槽函数,在工作线程的槽函数中,又会发射新的信号emitsignal,最后回到主线程中调用槽函数

 

2.继承QThread

示例

//头文件 #ifndef THREADSTART2_H #define THREADSTART2_H #include <QObject> #include <QThread> #include <iostream> #include <cassert> using namespace std; class threadstart2 : public QObject { Q_OBJECT public: explicit threadstart2(QObject *parent = nullptr); virtual ~threadstart2(); public slots: void handlesignals(); }; class workthread:public QThread { Q_OBJECT public: workthread(); virtual ~workthread(); protected: void run() override; signals: void emitsignal(); }; #endif // THREADSTART2_H //源文件 #include "threadstart2.h" threadstart2::threadstart2(QObject *parent) : QObject(parent) { workthread *wt=new workthread(); connect(wt, &workthread::emitsignal, this, &threadstart2::handlesignals); wt->start(); } threadstart2::~threadstart2() { cout<<__func__<<endl; } void threadstart2::handlesignals() { cout<<__func__<<endl; } workthread::workthread() : QThread() { cout<<__func__<<endl; } workthread::~workthread() { cout<<__func__<<endl; } void workthread::run() { while(1) { QThread::sleep(1); emit emitsignal(); cout<<QThread::currentThreadId()<<endl; } } //主函数 #include <QCoreApplication> #include "threadstart2.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); cout<<QThread::currentThreadId()<<endl; threadstart2 ts2; return a.exec(); }

示例代码的思路就是定义一个继承QThread的类并重写run函数,然后在主线程中实例化该类并启动线程,最后执行run函数并发出信号

这种线程的启动方式和第一种方式有一个区别,就是信号对应的槽函数在主线程中执行而不在新线程中执行

原因是因为:一个QThread实例位于实例化它的旧线程中,而不位于调用run函数的新线程中。 所以,所有QThread排队执行的槽函数也都将在旧线程中执行。

因此,如果想在新线程中调用槽函数,请使用第一种方式启动QT的线程。 

 

参考

https://doc.qt.io/qt-5/qthread.html#details

 

欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

最新回复(0)