一:引言
Qt中关于线程的使用,首先头文件QThead
Qt中两种线程创建方式:
以一个Progress Bar控件结合四个按钮为例:
常用的QThread函数:
start(): 启动线程,使线程进入运行状态,调用线程的run()方法。
run(): 线程的执行函数,需要在该函数中编写线程所需执行的任务。
quit(): 终止线程的事件循环,在下一个事件处理周期结束时退出线程。
wait(): 阻塞当前线程,直到线程执行完成或超时。
finished(): 在线程执行完成时发出信号。 t
erminate(): 强制终止线程的执行,可能导致资源泄漏和未定义行为。
isRunning(): 判断线程是否正在运行。
currentThreadId(): 返回当前线程的ID。
setPriority(): 设置线程优先级。
msleep(): 让当前线程休眠指定的毫秒数。 usleep():让当前线程休眠指定的微秒数。
二:方法一使用QThread类
首先添加一个自己定义的C++类文件或一个.h头文件,这里我直接添加一个自定义的MyThread.h的头文件,将实现代码写进头文件中
1.MyThread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QDebug>
class MyThread : public QThread{
Q_OBJECT
public:
MyThread(){}
~MyThread(){}
void run()//重写run函数
{
value=0;
qDebug()<<"thread id:"<<currentThreadId(); //currentThreadId();获取当前启动的线程的id号
while(1)
{
if(value == 101)
{
value=0;
}
while(pauseStatus)
{
usleep(1000);
}
emit valueChanged(value++);
//qDebug()<<value;
usleep(100000); //睡眠延时,防止CPU密集操作
}
}
signals:
void valueChanged(int);
public slots:
void setpause(bool flag)
{
this->pauseStatus = flag;
}
private:
int value =0;
bool pauseStatus =false; //停止继续标志位,停止变为true,继续为false;
};
#endif // MYTHREAD_H
2.widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QThread>
#include "MyThread.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
void on_pushButton_4_clicked();
private:
Ui::Widget *ui;
MyThread *t1;
};
#endif // WIDGET_H
3.widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
t1=new MyThread();
connect(t1,&MyThread::valueChanged,ui->progressBar,&QProgressBar::setValue);
//线程run执行结束(线程结束)时触发信号finished,deleteLater()回收t1的所有资源
//connect(t1,&MyThread::finished,t1,&QObject::deleteLater);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
//启动一个子线程
t1->start();
ui->pushButton->setEnabled(false);
}
void Widget::on_pushButton_2_clicked()
{
t1->setpause(true);
}
void Widget::on_pushButton_3_clicked()
{
t1->setpause(false);
}
void Widget::on_pushButton_4_clicked()
{
// t1->quit();
// t1->wait();
t1->terminate(); //杀死线程,线程会停止运行
ui->pushButton->setEnabled(true);
}
三:方法二使用 moveToThread()
moveToThread() 是 Qt 中用于将对象移动到另一个线程的方法。通过调用 moveToThread() 函数,可以将一个 QObject 对象从当前线程移动到另一个线程中,从而实现对象在新线程中执行特定的任务。
1.MyThread.h
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
#include <QThread>
#include <QDebug>
#include <QApplication>
class MyThread : public QObject{
Q_OBJECT
public:
MyThread(){}
~MyThread(){}
public slots:
void doWork()
{
value=0;
qDebug()<<"thread id:" << QThread::currentThreadId(); //currentThreadId();获取当前启动的线程的id号
//由于while(1)会占用当前线程的所有资源,因此该线程无法接收来自外部的事件
while (1)
{
if(value ==101)
{
value=0;
}
while(pauseStatus)
{
QApplication::processEvents();
QThread::usleep(10000);
}
emit valueChanged(value++);
QApplication::processEvents();//processEvents()接收外部的事件
QThread::usleep(100000);
}
}
signals:
void valueChanged(int);
public slots:
void setpauseStatus(bool flag)
{
this->pauseStatus=flag;
}
private:
int value =0;
bool pauseStatus=false;
};
#endif // MYTHREAD_H
2.widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "MyThread.h"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
signals:
void startWork();
void setPause(bool);
private slots:
void on_pushButton_clicked();
void on_pushButton_4_clicked();
void on_pushButton_2_clicked();
void on_pushButton_3_clicked();
private:
Ui::Widget *ui;
QThread t1; //定义线程类对象
MyThread *work; //定义普通的类对象指针
};
#endif // WIDGET_H
3.widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
work =new MyThread;//构造类对象
work->moveToThread(&t1);//将类对象移动到创建的t1线程中
//当startWork信号被触发,那么系统调用work的doWork函数,在线程t1中执行
connect(this,&Widget::startWork,work,&MyThread::doWork);
connect(work,&MyThread::valueChanged,ui->progressBar,&QProgressBar::setValue);
connect(this,&Widget::setPause,work,&MyThread::setpauseStatus);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
//启动t1线程,由于t1线程目前不做任何事情,因此处于挂起状态
t1.start();
//work->doWork(); //err:错误,work的所有东西都在线程中,Qt不支持跨线程调度
emit startWork();
}
void Widget::on_pushButton_2_clicked()
{
emit setPause(true);
}
void Widget::on_pushButton_3_clicked()
{
emit setPause(false);
}
void Widget::on_pushButton_4_clicked()
{
t1.terminate();
}