QT6 multithreaded QThread, which is the simplest

QT6 multithreaded QThread, which is the simplest

Qt has two multithreading methods. One is to implement the run function of QThread, and the other is to define an object inherited from QObject and put it into a Thread. In fact, the two methods have little difference and are convenient to use.

Qt officials suggest using the second method. The method of inheriting QObject is more flexible and the code is easier to maintain. This article introduces the second method.

1. Define and implement task classes

  • Two classes, Thread1 and Thread2, are defined. You must inherit QOBject, because only QOBject can use the moveToThread () method
  • Each class has three custom methods,
Method namemeaning
begintask
workingReturns the progress in the task
finishReturn value of end task

myThread.h, all code

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QObject>

class Thread1 : public QObject
{
    Q_OBJECT
public:
    explicit Thread1(QObject *parent = nullptr);
    void begin(int num);
signals:
    void working(int num);
    void finish(QString elapsedTime );

};


class Thread2 : public QObject
{
    Q_OBJECT
public:
    explicit Thread2(QObject *parent = nullptr);
    void begin(int num);
signals:
    void working(int num);
    void finish(QString elapsedTime );

};

#endif // MYTHREAD_H

2. Implementation task method

  • You only need to implement the being method, which is equivalent to the run in the thread, and the method name can be arbitrarily given.
  • Because working and finish are signal functions, they do not need to be implemented

myThread.cpp, all code

#include "myThread.h"
#include <QElapsedTimer>
#include <QDebug>
#include <QThread>

Thread1::Thread1(QObject *parent) : QObject(parent)
{

}
void Thread1::begin(int num){
    qDebug() <<" Thread 1:"<< num<<" || "<<QThread::currentThread();
    QElapsedTimer time;
    time.start();
    for(int i=0;i<num;i++){
        QThread::msleep(1); // Processing tasks
        emit working(i);
    }
    qDebug() <<"Thread 1, total time: "<<time.elapsed() <<" ms. ";
    emit finish(QString::number(time.elapsed()));

}

Thread2::Thread2(QObject *parent) : QObject(parent)
{

}

void Thread2::begin(int num)
{
    qDebug() <<" Thread 2:"<< num<<" || "<<QThread::currentThread();
    QElapsedTimer time;
    time.start();
    for(int i=0;i<num;i++){
       emit working(i);
        QThread::msleep(1); // Processing tasks
    }
    qDebug() <<"Thread 2, total time: "<<time.elapsed() <<" ms. ";
    emit finish(QString::number(time.elapsed()));
}

3, multithreaded in the window program.

In the QMainWindow.h file

  • First, two signal functions (starting1, starting1) are defined to facilitate the transmission of values to two threads. The signal function only needs to be declared without implementation.
signals:
    void starting1(int num);
    void starting2(int num);
  • Next, new two threads,
    QThread *t1= new QThread;
    QThread *t2= new QThread;
  • Then create the object of the task class
	Thread1 *work1 =new Thread1;
    Thread2 *work2 =new Thread2;

QMainWindow.h, all codes:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "myThread.h"
#include <QThread>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private slots:
    void on_startButton_clicked();

signals:
    void starting1(int num);
    void starting2(int num);


private:
    Ui::MainWindow *ui;


    QThread *t1= new QThread;
    QThread *t2= new QThread;

    //Create the object of the task class
    Thread1 *work1 =new Thread1;
    Thread2 *work2 =new Thread2;

};
#endif // MAINWINDOW_H

Code implementation:

In the constructor,

  • First allocate the thread. Because the class of work inherits Object, you can use the moveToThread() method to move the task to the thread to wait for the thread to start.
    work1->moveToThread(t1);
    work2->moveToThread(t2);
  • The value is transmitted to begin in the work task through the signal function starting, so that the task object can obtain the executed parameters
    //Pass value to child thread
    connect(this,&MainWindow::starting1,work1,&Thread1::begin);
    connect(this,&MainWindow::starting2,work2,&Thread2::begin);
  • Through the working signal function in the task object, the progress bar is updated in real time
    connect(work1,&Thread1::working,this,[=](int l){
        ui->thread1_Bar->setValue(l);
        ui->thread1_Bar->update();
    });

    connect(work2,&Thread2::working,this,[=](int l){
        ui->thread2_Bar->setValue(l);
        ui->thread2_Bar->update();
    });

  • Through the finish signal function in the task object, the main process obtains the result of thread execution
    connect(work1,&Thread1::finish,this,[=](QString s){
        ui->thread1_Edit->setText(s);
    });

    connect(work2,&Thread2::finish,this,[=](QString s){
        ui->thread2_Edit->setText(s);
    });

MainWindow.cpp, all codes

#include "MainWindow.h"
#include "ui_MainWindow.h"
#include "myThread.h"
#include <QThread>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //Allocation thread
    work1->moveToThread(t1);
    work2->moveToThread(t2);

    //Pass value to child thread
    connect(this,&MainWindow::starting1,work1,&Thread1::begin);
    connect(this,&MainWindow::starting2,work2,&Thread2::begin);

    //Receive the data sent by the child thread and update the progress bar
    connect(work1,&Thread1::working,this,[=](int l){
        ui->thread1_Bar->setValue(l);
        ui->thread1_Bar->update();
    });

    connect(work2,&Thread2::working,this,[=](int l){
        ui->thread2_Bar->setValue(l);
        ui->thread2_Bar->update();
    });

    connect(work1,&Thread1::finish,this,[=](QString s){
        ui->thread1_Edit->setText(s);
    });

    connect(work2,&Thread2::finish,this,[=](QString s){
        ui->thread2_Edit->setText(s);
    });

    connect(ui->startButton,&QPushButton::clicked,this,[=](){
		ui->thread1_Bar->setMaximum(1000);
        ui->thread2_Bar->setMaximum(2000);

		emit starting1(1000);
        emit starting2(2000);
        t1->start();
        t2->start();
    });


}

MainWindow::~MainWindow()
{
    work1->deleteLater();
    work2->deleteLater();
    t1->quit();
    t1->wait();
    t1->deleteLater();
    t2->quit();
    t2->wait();
    t2->deleteLater();
    delete ui;
}


void MainWindow::on_startButton_clicked()
{
    ui->thread1_Bar->setValue(0);
    ui->thread1_Edit->setText(0);
    ui->thread2_Bar->setValue(0);
    ui->thread2_Edit->setText(0);

}

4. Final effect:

The above is for reference only. If you have any questions, welcome to discuss.

Tags: C++ Qt Multithreading thread QtCreator

Posted on Mon, 20 Sep 2021 14:11:52 -0400 by BloodyMind