12 Qt Multithread Programming

Keywords: Qt

Qt opens multithreading, mainly for the class QThread. There are two ways, the first is to inherit the QThread with a class, and then rewrite the virtual function run(). When you want to open a new thread, you just need to instantiate the class and then call the function start() to open a multithread. The second method is to inherit a QObject class, and then use the moveToThread() function to open a thread slot function, which will take a lot of time to calculate the code into the thread slot function.

1. Multithreading before Qt4.6

  1. Create a new class MyThread based on QThread.
  2. Rewrite the virtual function void run() of MyThread class; that is, create a new function protected void run(), and define it.
  3. Where multithreading is needed, instance MyThread, and then call the function MyThread::start(), a thread is opened and the function run() is automatically run. Note that you can't call run() directly, but indirectly through start ().
  4. When the thread is stopped, the MyThread::wait() function is called to wait for the end of the thread and reclaim the thread resources.

The sample code is as follows:

mythread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>

class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = 0);
    ~MyThread();
protected:
    //Rewrite run function, thread execution function
    void run();
signals:
    //Signals emitted by a custom subthread after execution
    void isDone();
public slots:
};

#endif // MYTHREAD_H

mywidget.h

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>
#include <QTimer>
#include "mythread.h"
namespace Ui {
class MyWidget;
}

class MyWidget : public QWidget
{
    Q_OBJECT

public:
    explicit MyWidget(QWidget *parent = 0);
    ~MyWidget();

private slots:
    //Timer timeout processing slot function
    void dealTimeOut();
    void on_pushButton_clicked();
    //Processing Functions When Subthreads Exit
    void dealDone();
    //The slot function for subthread exit by clicking the red fork in the upper right corner
    void stopThread();
private:
    Ui::MyWidget *ui;
    QTimer MyTimer;
    MyThread* thread;

};

#endif // MYWIDGET_H

mythread.cpp

#include "mythread.h"
#include <QDebug>
MyThread::MyThread(QObject *parent) : QThread(parent)
{

}
//Rewrite run function, thread execution function
void MyThread::run()
{
    int i = 0;
    while(i < 10)
    {
        i++;
        sleep(1);
        qDebug()<<"I am a sub-thread, mine ID yes:"<<QThread::currentThreadId();
    }

    emit isDone();
}
MyThread::~MyThread()
{

}

mywidget.cpp

#include "mywidget.h"
#include "ui_mywidget.h"
#include <QThread>
#include <QDebug>
MyWidget::MyWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MyWidget)
{
    ui->setupUi(this);

    thread = new MyThread(this);
    //Correlation signal and slot
    connect(&this->MyTimer,QTimer::timeout,this,&MyWidget::dealTimeOut);
    connect(thread,&MyThread::isDone,this,&MyWidget::dealDone);
    connect(this,&MyWidget::destroy,this,&MyWidget::stopThread);
}
void MyWidget::stopThread()
{
    //Sign out
    thread->quit();
    //Wait for the child process function to execute, then exit
    thread->wait();
}
void MyWidget::dealDone()
{
    MyTimer.stop();
    qDebug()<<"Child Thread is Done";
}
void MyWidget::dealTimeOut()
{
    static int i = 0;
    i++;
    ui->lcdNumber->display(i);
    qDebug()<<"I am the main thread, mine ID Yes,"<<QThread::currentThreadId();
}
MyWidget::~MyWidget()
{
    delete ui;
}

void MyWidget::on_pushButton_clicked()
{
    if(MyTimer.isActive() == false)
    {
        //Start timer
        MyTimer.start(100);
    }
    //Start timer
    thread->start();
}

The final operation results are as follows:

I am the main thread, my ID is: 0x3f14

I am the main thread, my ID is: 0x3f14

I am the main thread, my ID is: 0x3f14

I am the main thread, my ID is: 0x3f14

I am a sub-thread, my ID is: 0x36d4

Subthread is Done

 

2. Multithreading after Qt4.6

  1. Create a new class, inherit and QObject
  2. Create a slot function in the class to run the code in multithreading. All time-consuming codes run in this slot function.
  3. Instance of a myThread object of this class. Note that the parent object cannot be specified, because the parent object is specified later through moveToThread
  4. Instance a thread of the QThread object, at which point the parent object can be specified
  5. To transfer the QThread object to the instance object myThread of the new class, you can use the function void QObject::moveToThread(QMyThread *thread); for example, myThread - > moveToThread (thread)
  6. Start thread object thread - > start ();
  7. Start the slot function of the new class myThread by means of signal and slot
  8. The quit() and wait() functions of threads are used to wait for sub-threads to exit. Note that wait() waits until the slot function is executed before returning. If the slot function is not finished, the program may get stuck.

The sample code is as follows:

mthread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QObject>
#include <QThread>
class MyThread : public QObject
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = 0);
    ~MyThread();
    //Custom thread processing function can not be called directly, otherwise the function and the main thread are in one thread.
    //If the function is time-consuming, the thread will get stuck.
    void myTimeOut();
signals:
    //Custom signals to notify the main thread to perform related operations
     void mysignals();

public:
     bool isStop;
public slots:
};

#endif // MYTHREAD_H

mywidget.h

#ifndef MYWIDGET_H
#define MYWIDGET_H

#include <QWidget>
#include "mythread.h"
namespace Ui {
class MyWidget;
}

class MyWidget : public QWidget
{
    Q_OBJECT

public:
    explicit MyWidget(QWidget *parent = 0);
    ~MyWidget();
signals:
    void myStartThread();
private slots:
    //Callback function of start button
    void on_startBtn_clicked();
    //Callback function of stop button
    void on_pushButton_2_clicked();
    //Slot function for processing subprocesses
    void dealSignals();
    //Slot function when exiting program
    void stopThread();


private:
    //Custom Thread Class Objects
    MyThread* mythread;
    //Thread class object
    QThread* thread;
    Ui::MyWidget *ui;
};

#endif // MYWIDGET_H

mypthread.cpp

#include "mythread.h"
#include<QDebug>
MyThread::MyThread(QObject *parent) : QObject(parent)
{
    isStop = false;
}

MyThread::~MyThread()
{

}

void MyThread::myTimeOut()
{
    while(!isStop)
    {
        qDebug()<<"I am a sub-thread, mine ID Yes,"<<QThread::currentThreadId();
        QThread::sleep(1);
        //Send a signal to the main thread
        emit mysignals();
    }
}

mywidget.cpp

#include "mywidget.h"
#include "ui_mywidget.h"
#include <QDebug>
MyWidget::MyWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MyWidget)
{
    ui->setupUi(this);
    //Allocate space dynamically, not the parent object
    mythread = new MyThread;

    //Create subthreads
    thread = new QThread(this);

    //Adding a custom thread to a sub-thread, that is, specifying the child thread bit and the father of the custom thread
    mythread->moveToThread(thread);

    //Establish the signal and slot of main thread and sub-thread
    connect(mythread,&MyThread::mysignals,this,&MyWidget::dealSignals);

    //The thread processing function of sub-threads is invoked by means of signal and slot
    connect(this,&MyWidget::myStartThread,mythread,&MyThread::myTimeOut);

    //When the operation is closed, the thread exit operation is performed
    connect(this,&MyWidget::destroyed,this,&MyWidget::stopThread);
    qDebug()<<"I am the main thread, mine ID Yes,"<<QThread::currentThreadId();
}
//Thread exit operation
void MyWidget::stopThread()
{
    if(thread->isRunning())
    {
        mythread->isStop = true;
        thread->quit();
        thread->wait();
    }

}
//Main thread operates slot function according to sub-thread signal
void MyWidget::dealSignals()
{
    static int i = 0;
    i++;
    ui->lcdNumber->display(i);

}
MyWidget::~MyWidget()
{
    delete ui;
}
//Slot function of start button
void MyWidget::on_startBtn_clicked()
{
    if(false == thread->isRunning())
    {
        //Start subthreads, but do not start handlers for custom threads
        thread->start();
        mythread->isStop = false;
        emit myStartThread();
    }
}
//Slot function of stop button
void MyWidget::on_pushButton_2_clicked()
{
    if(thread->isRunning())
    {
        mythread->isStop = true;
        thread->quit();
        thread->wait();
    }
}

The code runs as follows:

I am the main thread, my ID is: 0x19e0

I am a sub-thread, my ID is: 0x4430

I am a sub-thread, my ID is: 0x4430

Posted by carrotcake1029 on Sat, 11 May 2019 00:14:39 -0700