Qt文档阅读笔记-Qt工作笔记-QThread解析与实例(主线程发送信号给子线程)
发布日期:2021-06-30 10:56:35 浏览次数:2 分类:技术文章

本文共 4419 字,大约阅读时间需要 14 分钟。

目录


QThread

官方解析

Detailed Description

QThread类提供了跨平台的线程管理的API。

QThread对象在程序中管理一个线程。 使用run()来执行,默认情况下run()通过调用exec()实现事件循环,并且run()使得QThread的对象的线程中Qt的事件循环跑起来。
可以用QObject::moveToThread()使worker对象放入线程中。

class Worker : public QObject  {      Q_OBJECT  public slots:      void doWork(const QString &parameter) {          QString result;          /* ... here is the expensive or blocking operation ... */          emit resultReady(result);      }  signals:      void resultReady(const QString &result);  };  class Controller : public QObject  {      Q_OBJECT      QThread workerThread;  public:      Controller() {          Worker *worker = new Worker;          worker->moveToThread(&workerThread);          connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);          connect(this, &Controller::operate, worker, &Worker::doWork);          connect(worker, &Worker::resultReady, this, &Controller::handleResults);          workerThread.start();      }      ~Controller() {          workerThread.quit();          workerThread.wait();      }  public slots:      void handleResults(const QString &);  signals:      void operate(const QString &);  };

在这个代码里面Worker的槽函数在另外一个线程中执行。但可以使用信号与槽让任意的object对象(继承了QObject,并且带有Q_OBJECT宏)信号连接Worker的槽函数。这种跨线程的信号与槽的连接方式是安全的,这得归功于connect()函数的第五个参数(参考链接)默认调用了queued connections。
另外一种方式让代码运行在其他线程的方式是,子类化QThread类,并且重新实现run()函数,栗子如下:

class WorkerThread : public QThread  {      Q_OBJECT      void run() Q_DECL_OVERRIDE {          QString result;          /* ... here is the expensive or blocking operation ... */          emit resultReady(result);      }  signals:      void resultReady(const QString &s);  };  void MyObject::startWorkInAThread()  {      WorkerThread *workerThread = new WorkerThread(this);      connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);      connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);      workerThread->start();  }

在这个栗子中,thread将会在函数返回的时候退出。他们将不会在线程中运算事件循环,除非他们调用exec().
要注意QThread实例存在与谁实例化他的线程中,而不是在谁调用了run()这个函数的线程中。这就意味着QThread以队列连接的信号与槽,将会执行在实例化他的线程中,而不是调用run()函数这个线程中。因此如果希望在新线程里面调用槽函数得使用worker对象显示出的方式;不应该将槽函数直接实例在子类化的QThread中。
当子类化QThread类后,构造函数会旧的(实例化他的)那个线程中执行,而run()的执行将会在新线程中。如果这两个函数都访问了成员变量,从两个不同的线程中访问这个变量,要检测这么做是否安全!

Note:要小心,在不同对象或者线程中交互。查看Synchronizing Threads查看详情!

 

博主栗子

子线程发射信号给主线程

当子线程里面emit一个signal给主线程,这是十分常见的,但主线程emit一个signal给子线程那么会发送些什么呢!

运行截图如下:

源码瑞星啊:

widget.h

#ifndef WIDGET_H#define WIDGET_H#include 
class QThread;class Worker;class Widget : public QWidget{ Q_OBJECTpublic: Widget(QWidget *parent = 0); ~Widget();protected: void timerEvent(QTimerEvent *event)Q_DECL_OVERRIDE;signals: void hello(); void sendMsg();private: QThread *thread[3]; Worker *worker[3];};#endif // WIDGET_H

worker.h

#ifndef WORKER_H#define WORKER_H#include 
class Worker : public QObject{ Q_OBJECTpublic: Worker(QObject *parent = 0);public slots: void beginToWork(); void mainThreadMsg();};#endif // WORKER_H

main.cpp

#include "widget.h"#include 
int main(int argc, char *argv[]){ QApplication a(argc, argv); Widget w; w.show(); return a.exec();}

widget.cpp

#include "widget.h"#include "worker.h"#include 
#include
Widget::Widget(QWidget *parent) : QWidget(parent){ for(int i=0;i<3;i++){ thread[i]=new QThread; worker[i]=new Worker; worker[i]->moveToThread(thread[i]); connect(thread[i],&QThread::finished,worker[i],&QObject::deleteLater); connect(this,&Widget::hello,worker[i],&Worker::beginToWork); connect(this,SIGNAL(sendMsg()),worker[i],SLOT(mainThreadMsg()),Qt::DirectConnection); thread[i]->start(); } emit hello(); startTimer(1000);}Widget::~Widget(){ for(int i=0;i<3;i++){ thread[i]->quit(); thread[i]->wait(); delete thread[i]; delete worker[i]; }}void Widget::timerEvent(QTimerEvent *event){ Q_UNUSED(event) emit sendMsg();// for(int i=0;i<3;i++){// qDebug()<<"main thread, worker "<
mainThreadMsg();// }}

worker.cpp

#include "worker.h"#include 
#include
Worker::Worker(QObject *parent) : QObject(parent){}void Worker::beginToWork(){ while(true){ QThread::sleep(2); qDebug()<
<<" beginToWork"; mainThreadMsg(); }}void Worker::mainThreadMsg(){ qDebug()<<"mainThreadMsg called!"<

 

转载地址:https://it1995.blog.csdn.net/article/details/82732980 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Qt文档阅读笔记-Qt工作笔记QProcess::finished的解析与实例
下一篇:软件设计师学习笔记-数据结构与算法基础

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年04月10日 15时25分14秒