Qt:线程

一个Qt窗口生成后,为什么拖动窗口,窗口可以随着鼠标移动或放大缩小
因为对窗口操作后,都有对应的事件产生,Qt在其框架中对这些事件进行了默认处理
一个Qt程序默认只有一个线程,称为主线程(也叫ui线程),主要处理窗口的事件(比如鼠标拖动,缩放,窗口控件对象数据的更新)
不能用子线程处理这些事,如果子线程要操作窗口,只能先将数据传递给主线程,由主线程操作

常用函数

分为三个部分,公有函数、公有槽函数,信号,Qt提供的静态成员函数
父对象和父类是两回事,父类是继承关系,父对象是从属关系

// 构造函数
QThread::QThread(QObject *parent = Q_NULLPTR);
指定一个父对象就可以了

// 判断线程中的任务是不是处理完毕了
bool QThread::isFinished() const;
// 判断子线程是不是在执行任务
bool QThread::isRunning() const;

// Qt中的线程可以设置优先级
// 得到当前线程的优先级
Priority QThread::priority() const;
void QThread::setPriority(Priority priority);
优先级:
    QThread::IdlePriority         --> 最低的优先级
    QThread::LowestPriority
    QThread::LowPriority
    QThread::NormalPriority
    QThread::HighPriority
    QThread::HighestPriority
    QThread::TimeCriticalPriority --> 最高的优先级
    
    QThread::InheritPriority      --> 子线程和其父线程的优先级相同, 默认是这个
// 退出线程, 停止底层的事件循环
// 退出线程的工作函数
void QThread::exit(int returnCode = 0);
// 调用线程退出函数之后, 线程不会马上退出因为当前任务有可能还没有完成, 调回用这个函数是
// 调用wait后会等待任务执行, 执行完退出线程, 一般情况下会在 exit() 后边调用这个函数
bool QThread::wait(unsigned long time = ULONG_MAX);

// 和调用 exit() 效果是一样的
// 调用这个函数之后, 再调用 wait() 函数
[slot] void QThread::quit();

// 启动子线程
[slot] void QThread::start(Priority priority = InheritPriority);

// 线程退出, 可能是会马上终止线程, 一般情况下不使用这个函数
[slot] void QThread::terminate();

信号

// 线程中完成后, 会发出该信号
[signal] void QThread::finished();

// 发出该信号后表示线程开始工作,启动线程后没必要捕捉该信号
[signal] void QThread::started();

主线程和子线程间通过信号和槽进行数据传递

静态函数

// 返回一个指向管理当前执行线程的QThread的指针
[static] QThread *QThread::currentThread();

// 返回可以在系统上运行的理想线程数 == 和当前电脑的 CPU 核心数相同
[static] int QThread::idealThreadCount();

// 线程休眠函数
[static] void QThread::msleep(unsigned long msecs);	// 单位: 毫秒
[static] void QThread::sleep(unsigned long secs);	// 单位: 秒
[static] void QThread::usleep(unsigned long usecs);	// 单位: 微秒

任务处理函数

// 子线程要处理什么任务, 需要写到 run() 中
[virtual protected] void QThread::run();

该函数没有参数和返回值,是一个受保护的虚函数,如果让子线程处理某些任务,需要将任务写到run内部,调用start函数就能执行线程内部的run函数

受保护说明该函数不能在类外使用,需要通过调用start槽函数使run函数运行执行任务

使用方式

方式1:

  • 创建线程类,该类继承QThread类
  • 在线程的子类中重写run函数
  • 在主线程类中new一个子线程的类对象,让该子线程对象调用start函数

子类头文件

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

protected:
    void run();

signals:
    // 自定义信号, 传递数据
    void curNumber(int num);

public slots:
};

子类源文件

#include "mythread.h"
#include <QDebug>
MyThread::MyThread(QObject *parent) : QThread(parent)
{}

void MyThread::run()
{
    qDebug() << "当前线程对象的地址: " << QThread::currentThread();

    int num = 0;
    while(1)
    {
        emit curNumber(num++);
        if(num == 10000000)
        {
            break;
        }
        QThread::usleep(1);
    }
    qDebug() << "run() 执行完毕, 子线程退出...";
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "mythread.h"
#include <QDebug>

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

    qDebug() << "主线程对象地址:  " << QThread::currentThread();
    // 创建子线程
    MyThread* subThread = new MyThread;

    connect(subThread, &MyThread::curNumber, this, [=](int num)
    {
        ui->label->setNum(num);
    });

    connect(ui->startBtn, &QPushButton::clicked, this, [=]()
    {
        // 启动子线程
        subThread->start();
    });
}

MainWindow::~MainWindow()
{
    delete ui;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: 在Qt中,可以通过QObject::moveToThread()函数将对象及其子对象的线程相关性进行修改。这个函数可以将一个对象移动到指定的线程中。如果对象有父对象,那么就不能直接移动该对象。通过将对象移动到另一个线程中,可以在对象所在的线程中修改线程变量。举个例子,如果你想要修改一个线程中的变量,可以先将该对象移动到目标线程,然后在目标线程中修改变量的值。这样就可以在目标线程中修改线程变量了。另外,每个线程都可以有自己的事件循环,可以使用QThread::exec()启动事件循环。在事件循环中,可以处理线程中的事件,包括修改线程变量。123 #### 引用[.reference_title] - *1* *3* [Qt线程与QObjects](https://blog.csdn.net/zhizhengguan/article/details/115674671)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}} ] [.reference_item] - *2* [Qt线程同步:互斥锁QMutextLocker 、读写锁 QReadWriteLock、信号量 QSemaphore、 条件变量...](https://blog.csdn.net/qq_16504163/article/details/130493328)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值