Qt之QThread的使用

一:引言

        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();
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值