当前位置: 首页 > article >正文

Qt中使用线程之QThread

使用Qt中自带的线程类QThread时

1、需要定义一个子类继承自QThread

2、重写run()方法,在run方法中编写业务逻辑

3、子类支持信号槽

4、子类的构造函数的执行是在主线程进行的,而run方法的执行是在子线程中进行的

常用方法

静态方法

获取线程id

可以得到当前线程的id

[static noexcept] Qt::HANDLE QThread::currentThreadId()

线程睡眠

 void msleep(unsigned long msecs)//单位毫秒
 void sleep(unsigned long secs)//单位秒
 (since 6.6) void sleep(std::chrono::nanoseconds nsecs)//单位纳秒
 void usleep(unsigned long usecs)//单位微秒

公共方法

判断线程是否执行完毕

bool QThread::isFinished() const

判断线程是否正在运行

bool QThread::isRunning() const

判断线程是否被请求中断了

bool QThread::isInterruptionRequested() const

可以在子线程中的run函数中通过这个函数获知是否需要中断退出了

发出中断请求

调用这个方法可以向线程发起中断请求,调用后:isInterruptionRequested()会返回true

void QThread::requestInterruption()

等待线程

是一个阻塞函数,调用他来确保线程已经执行完毕

bool QThread::wait(QDeadlineTimer deadline = QDeadlineTimer(QDeadlineTimer::Forever))

通常使用其默认参数,如果线程一直不执行完毕,那么该函数的调用者将会一直被阻塞,直到线程执行完毕

公有槽函数

启动线程

通常我们调用该函数来启动线程

[slot] void QThread::start(QThread::Priority priority = InheritPriority)

终止线程

通常我们调用该方法强制终止一个线程,但不建议

[slot] void QThread::terminate()

常用信号

线程开始执行时会发出started信号

线程执行完毕退出后会发出finished信号 

这两个都是私有信号,只能被连接,不能用来主动发射

 void finished()
 void started()

举例:

点击开启按钮,会开启一个线程

点击关闭按钮,会发出中断请求,使得线程退出

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include<QThread>
#include<QPushButton>

class Thread01:public QThread
{
    Q_OBJECT
public:
    Thread01(int num):m_num(num)
    {
        //构造函数的调用是在主线程
        //可以打印线程id,查看区别
        qDebug()<<"线程id:"<<QThread::currentThreadId();
    }
    ~Thread01()=default;

protected:
    //重写run方法
    void run() override
    {
        //run函数在子线程中运行
        qDebug()<<"线程id:"<<QThread::currentThreadId();
        while(1)
        {
            //如果请求中断的话就退出
            if(isInterruptionRequested())
            {
                return;
            }
            //循环自增,然后打印
            qDebug()<<m_num++;
        }
    }
private:
    int m_num=0;

};


class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr) : QWidget(parent)
    {
        resize(300,300);
        QPushButton* btn=new QPushButton("开启线程",this);
        btn->setGeometry(10,10,100,100);

        QPushButton* btn2=new QPushButton("退出线程",this);
        btn2->setGeometry(10,btn->geometry().bottom()+10,100,100);

        //创建线程
        Thread01* th=new Thread01(100);//从100开始自增

        connect(btn,&QPushButton::clicked,this,[=](){
            //开启线程
            if(!th->isRunning())
            {
                th->start();
            }
        });
        connect(btn2,&QPushButton::clicked,this,[=](){
            //线程正在执行的话
            if(th->isRunning())
            {
                //中断线程
                th->requestInterruption();
            }
            //使用wait方法确保线程退出了
            if(th->wait())
            {
                qDebug()<<"线程退出了";
            }
        });



    }
    ~Widget()=default;
private:

};
#endif // WIDGET_H

学习链接:https://github.com/0voice


http://www.kler.cn/news/360849.html

相关文章:

  • LeetCode 3192.使二进制数组全部等于 1 的最少操作次数 II:位运算模拟
  • 如何使用 Browserless 抓取动态网站?
  • 优化多表联表查询的常见方法归纳
  • 力扣(leetcode)每日一题 3191 使二进制数组全部等于 1 的最少操作次数 I |贪心
  • iOS GCD的基本使用
  • 平衡二叉树最全代码
  • pdf怎么合并在一起?pdf合并的简单方法
  • Vue事件处理
  • Neo4J的APOC插件安装与配置
  • pikachu靶场CSRF-get测试报告
  • 八股面试2(自用)
  • http作业
  • Python(numpy库常见函数)
  • Java框架之MyBatis Plus
  • 贵州师范大学2025考研初复试资料清单一览
  • PLL锁相环带宽定义,以及PI参数自动整定
  • 使用SpringBoot自定义注解+AOP+redisson锁来实现防接口幂等性重复提交
  • 加密,混淆,摘要,序列化的理解
  • 柔性数组的使用
  • 基于ECS和NAS搭建个人网盘