Qt线程简单使用二:QObject~创建任务类

Posted 十一的杂文录

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt线程简单使用二:QObject~创建任务类相关的知识,希望对你有一定的参考价值。

 
需求:
  点击QPushButton按钮,QLabel中的数字,不断累加,一直到999。
 
做法:
  创建任务类,用来完成任务,创建子线程,将任务类放到子线程中,点击QPushButton后,先发送信号启动任务类的任务,然后启动线程,通过任务类while循环,不断发送累加的数字会主线程,修改QLabel中的数字
 
其他:
  一个任务类,可以创建多个任务,写法麻烦一点,视情况决定是否采用这种方法。
 
 
主要代码:
// MyThread.h

#pragma once

#include <QObject>
#include <QThread>

class MyWork  : public QObject

    Q_OBJECT

public:
    MyWork(QObject *parent=nullptr);
    ~MyWork();
    
    void work();

signals:
    void sendNum(int num);
;

 

// MyThread.cpp

#include "MyThread.h"

MyWork::MyWork(QObject *parent)
    : QObject(parent)


MyWork::~MyWork()


void MyWork::work()

    int num = 0;
    while (num < 1000)
    
        emit sendNum(num);
        num++;
        QThread::msleep(5);
    

 

 

// QtWidgetsApplication1.cpp


#include "MyThread.h"


MyWidget::MyWidget(QWidget *parent)
    : QDialog(parent)

    ui.setupUi(this);

    // 1.创建子线程对象
    QThread* t = new QThread;

    // 2.创建任务类对象
    MyWork* work = new MyWork;

    // 3.将任务类对象移动到子线程对象中
    work->moveToThread(t);

    // 开始工作
    connect(this, &MyWidget::startWork, work, &MyWork::work);
    connect(work, &MyWork::sendNum, this, [=](int num) ui.label->setText(QString::number(num)); );
    connect(ui.pushButton, &QPushButton::clicked, this, [=]() 
        
            emit startWork();
            t->start();
        );

    // 释放
    // 第一种:创建的时候,添加this参数,这样会自动析构,例:QThread* t = new QThread(this);
    // 第二种,手动释放
    connect(this, &MyWidget::destroy, [=]() 
        t->quit();
        t->wait();
        delete t;

        delete work;
        );
    

 

 
 
 
 
 
 
 

Qt线程的简单使用

Qt中线程的一种创建方式,就是使用QObject::moveToThread()函数。如下,直接上源代码,可以把费时的任务放到doWork()方法里进行,不阻塞主线程。

 1 #ifndef WORKER_H
 2 #define WORKER_H
 3 
 4 #include <QObject>
 5 
 6 class Worker : public QObject
 7 {
 8     Q_OBJECT
 9 
10 public:
11     Worker();
12     ~Worker();
13 public slots:
14     void doWork();
15 private:
16     
17 };
18 
19 #endif // WORKERR_H
 1 #include "Worker.h"
 2 #include <QDebug>
 3 
 4 Worker::Worker()
 5 {
 6 
 7 }
 8 
 9 Worker::~Worker()
10 {
11 
12 }
13 void Worker::doWork()
14 {
15     for (int i = 0;i < 10000;i++)
16     {
17         qDebug() << i;
18     }
19 }

需要在主程序中,关联相应的信号和槽,

1 m_pWorker = new Worker;
2     m_pWorkerThread = new QThread(this);
3 
4     connect(m_pWorkerThread, SIGNAL(started()),m_pWorker, SLOT(doWork()));
5     connect(m_pWorkerThread, SIGNAL(finished()), m_pWorker, SLOT(deleteLater()));
6     m_pWorker->moveToThread(m_pWorkerThread);

同时在析构函数中,也要进行想要的资源释放,

 1 disconnect(m_pWorkerThread, SIGNAL(started()),m_pWorker, SLOT(doWork()));
 2     disconnect(m_pWorkerThread, SIGNAL(finished()), m_pWorker, SLOT(deleteLater()));
 3     if (m_pWorkerThread)
 4     {
 5         if (m_pWorkerThread->isRunning())
 6         {
 7             m_pWorkerThread->quit();
 8             m_pWorkerThread->wait();
 9         }
10         delete m_pWorkerThread;
11         m_pWorkerThread = NULL;
12     }
13     if (m_pWorker)
14     {
15         delete m_pWorker;
16         m_pWorker = NULL;
17     }

最后提一点,如果需要在doWork()函数传递参数中,涉及传递的参数是自定义的类型时,需要将其注册为元类型。

如下的示例,1.我将需要计算的数据先进行预处理之后,发送我自定义的geoDataReady信号。

2.在线程中进行几何计算,完成之后,又将计算完成之后的数据发送回主函数。如下。

1 qRegisterMetaType<std::vector<MyGeometry*>>("std::vector<MyGeometry* >");
2     //在线程中进行几何运算
3     m_pGeoWorker = new CMyWork;
4     connect(this, SIGNAL(geoDataReady(const std::vector<MyGeometry> &)), m_pGeoWorker, SLOT(get(const std::vector<MYGeometry* > &)));
5     connect(m_pGeoWorker, SIGNAL(geoResultCompleted(const std::vector<MYGeometry* > &)), this, SLOT(draw(const std::vector<MYGeometry* > &)));
6     connect(&m_geoThread, SIGNAL(finished()), m_pGeoWorker, SLOT(deleteLater()));
7     m_pGeoWorker->moveToThread(&m_geoThread);
8     m_geoThread.start();

 

以上是关于Qt线程简单使用二:QObject~创建任务类的主要内容,如果未能解决你的问题,请参考以下文章

Qt线程的简单使用系列

QT多线程操作

Qt多线程——方式2

QT之QObject简单介绍

Qt入门教程QObject篇重入性和线程安全

Qt入门教程QObject篇多线程方案分析