一、说明
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
四、代码演示
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
#include <QThread>
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 <QDebug>
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 <QMainWindow>
#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 <QDebug>
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来区分不同的线程