16、Qt线程(一):继承QThread,重写run

一、说明

Qt提供了3个类4种方式创建线程:

1、QThread

①继承QThread类,重写run()函数

②继承QObject类,使用moveToThread()函数

2、使用QtConCurrent并发模块的run()函数

3、继承QRunnable类

二、功能说明

1、通过继承QThread,重写run的方式实现多线程

2、点击“开始”按钮启动子线程,同时通过信号槽的方式给子线程发送“开始”字符串;

3、子线程每隔1秒向主线程发送累加数;

4、点击"停止"按钮,通过函数调用的方式停止子线程;

5、注:

①子线程构造函数、被主线程调用的函数(stop())和信号槽方式调用的函数(doSendData())都是在主线程

②只有run()和run()调用的函数showValue()在子线程

三、项目创建

1、新建Qt Widgets Application应用,名称为ThreadRun,基类选择QMainWindow;

2、mainwindow.ui中放入两个Push Button按钮,第一个text改为“开始”,objectNme改为startPushButton,第二个text改为“停止”,objectNme改为stopPushButton

3、添加新的C++类,名称为MyThread,基类设置为QThread

四、代码演示

1、mythread.h代码
#ifndef MYTHREAD_H
#define MYTHREAD_H

#include 
#include 

class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = nullptr);

public slots:
    void stop(); //线程停止

    void doSendData(QString); //接收主线程发送的字符串

protected:
    void run(); //线程启动函数

signals:
    void sendValue(int); //给主线程发送累加数

private slots:
    void showValue(); //显示累加数

private:
    volatile bool stopped; //线程停止标识

    int value; //累加数
};

#endif // MYTHREAD_H

2、mythread.cpp代码

#include "mythread.h"
#include 

MyThread::MyThread(QObject *parent) : QThread(parent)
{
    stopped = false;
    qDebug() << "创建 子线程id:" << QThread::currentThreadId();
}

/**
* @brief MyThread::stop 线程停止
*/
void MyThread::stop()
{
    stopped = true;
    qDebug() << "stop 子线程id:" << QThread::currentThreadId();
}

/**
* @brief MyThread::doSendData 接收显示主线程发送的字符串
* @param str
*/
void MyThread::doSendData(QString str)
{
    qDebug() << str << "doSendData 子线程id:" << QThread::currentThreadId();
}

/**
* @brief MyThread::run 子线程开始,自动调用run()函数
*/
void MyThread::run()
{
    value = 0;

    qDebug() << "run 子线程id:" << QThread::currentThreadId();
    while(!stopped)
    {
        showValue();
        msleep(1000); //延迟1秒
    }
    stopped = false;
}

/**
* @brief MyThread::showValue 显示并给主线程发送累加数
*/
void MyThread::showValue()
{
    qDebug() << value << "show子线程id:"<< QThread::currentThreadId();

    emit sendValue(value); //数据发送给主线程
    value++;
}

3、mainwindow.h代码

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include "mythread.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

signals:
    void sendData(QString); //给子线程发送字符串

private slots:
    void on_startPushButton_clicked();

    void on_stopPushButton_clicked();

    void doSendValue(int); //接收子线程发送的累加数

private:
    Ui::MainWindow *ui;

    MyThread *m_myThread; //子线程对象
};

#endif // MAINWINDOW_H

4、mainwindow.cpp代码

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include 

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

    qDebug() << "主线程id:" << QThread::currentThreadId();

    m_myThread = new MyThread(this);
    //接收子线程数据
    connect(m_myThread, &MyThread::sendValue, this, &MainWindow::doSendValue);
    //给子线程发送数据
    connect(this, &MainWindow::sendData, m_myThread, &MyThread::doSendData);

    ui->startPushButton->setEnabled(true);
    ui->stopPushButton->setEnabled(false);
}

MainWindow::~MainWindow()
{
    if(m_myThread->isRunning())
    {
        m_myThread->stop();
    }
    m_myThread->quit(); //将子线程停止
    m_myThread->wait(); //等待子线程的运行结束后再停止

    delete ui;
}

/**
* @brief MainWindow::on_startPushButton_clicked 线程开始
*/
void MainWindow::on_startPushButton_clicked()
{
    emit sendData("开始");

    qDebug() << "主线程 startButtonid:" << QThread::currentThreadId();

    m_myThread->start(); //子线程开始,自动调用run()函数

    ui->startPushButton->setEnabled(false);
    ui->stopPushButton->setEnabled(true);
}

/**
* @brief MainWindow::on_stopPushButton_clicked 线程停止
*/
void MainWindow::on_stopPushButton_clicked()
{
    qDebug() << "主线程 stopButtonid:" << QThread::currentThreadId();
    if(m_myThread->isRunning())
    {
        m_myThread->stop();
        ui->startPushButton->setEnabled(true);
        ui->stopPushButton->setEnabled(false);
    }
}

/**
* @brief MainWindow::doSendValue 接收子线程发送的累加数
* @param value
*/
void MainWindow::doSendValue(int value)
{
    qDebug() << value << "doSendValue 线程id:"<< QThread::currentThreadId();
}

五、运行测试

先点击开始,一会再点击停止,输出框输出如下内容,根据线程id来区分不同的线程

16、Qt线程(一):继承QThread,重写run_第1张图片

你可能感兴趣的:(Qt小功能,qt)