Qt中多线程

在Qt中实现多线程主要有两种常用方式:基于QThread的子类化QObject+moveToThread的Worker模式。以下是详细说明和示例代码:


1. 传统方法:继承 QThread(适用于简单任务)

cpp 复制代码
#include <QThread>
#include <QDebug>

class MyThread : public QThread {
    Q_OBJECT
protected:
    void run() override {
        for(int i=0; i<5; i++){
            qDebug() << "Thread:" << i;
            sleep(1); // 模拟耗时操作
        }
    }
};

// 使用方式
MyThread thread;
thread.start(); // 启动线程
thread.wait();  // 等待线程结束(可选)

注意

  • 直接在run()中编写业务逻辑,但不要在此线程中操作GUI组件。
  • Qt4时代的经典方法,Qt5之后推荐Worker模式。

2. 推荐方法:Worker对象 + moveToThread(事件驱动)

cpp 复制代码
#include <QObject>
#include <QThread>
#include <QDebug>

class Worker : public QObject {
    Q_OBJECT
public slots:
    void doWork() {
        for(int i=0; i<5; i++){
            qDebug() << "Worker in thread:" << QThread::currentThreadId();
            QThread::sleep(1);
        }
        emit workFinished();
    }
signals:
    void workFinished();
};

// 使用方式
QThread *thread = new QThread;
Worker *worker = new Worker;
worker->moveToThread(thread);

// 连接信号与槽
QObject::connect(thread, &QThread::started, worker, &Worker::doWork);
QObject::connect(worker, &Worker::workFinished, thread, &QThread::quit);
QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater);
QObject::connect(thread, &QThread::finished, worker, &QObject::deleteLater);

thread->start(); // 启动线程事件循环

优势

  • 利用Qt的事件循环,避免阻塞线程。
  • 通过信号槽实现线程间通信,天然线程安全。
  • 资源管理更清晰,通过deleteLater自动释放对象。

3. 线程安全与信号槽

  • 跨线程通信:Qt信号槽自动排队(QueuedConnection),无需手动同步。
  • 共享数据保护 :使用QMutexLockerQReadWriteLock保护临界区。
cpp 复制代码
// 示例:使用QMutex保护共享数据
QString sharedData;
QMutex mutex;

void modifyData() {
    QMutexLocker locker(&mutex);
    sharedData = "Modified";
}

4. 线程池(QRunnable)

适用于需要频繁创建/销毁线程的场景:

cpp 复制代码
#include <QRunnable>
#include <QThreadPool>

class Task : public QRunnable {
    void run() override {
        qDebug() << "Task running in thread pool";
    }
};

// 使用方式
Task *task = new Task;
QThreadPool::globalInstance()->start(task);

关键注意事项

  1. GUI操作限制:所有界面操作必须在主线程完成,通过信号将结果传递回UI线程。
  2. 事件循环:Worker模式依赖线程的事件循环(默认已启动)。
  3. 资源释放 :通过finished信号触发deleteLater,避免野指针。
  4. 避免阻塞:耗时应放在子线程,主线程保持响应。

示例场景:后台计算更新进度

cpp 复制代码
// Worker类中定义进度信号
signals:
    void progressUpdated(int percent);

// UI线程连接信号
QObject::connect(worker, &Worker::progressUpdated, 
    [](int value){ progressBar->setValue(value); });

通过上述方法,Qt多线程编程既能保持界面流畅,又能高效利用多核CPU资源。

相关推荐
傻啦嘿哟4 分钟前
某招聘平台爬虫:爬取招聘岗位数据,分析各城市薪资水平
开发语言·爬虫·python
2501_933670795 分钟前
2026秋招量化分析岗技能栈:Python、SQL、统计建模、回测项目怎么准备
开发语言·python·sql
李少兄1 小时前
JavaScript 数据类型完全指南
开发语言·javascript·ecmascript
Seoyoneh1 小时前
Agentic Workflow编排架构:云客服从“被动响应”迈向“主动执行”的技术实现
java·开发语言·架构
Tangyuewei2 小时前
Java 写 Agent:模型只是组件
java·开发语言
小玮看世界2 小时前
[Python]从合并区间到传感器融合区:合并区间在传感器区域融合的实际落地
开发语言·python
繁星蓝雨3 小时前
C++的设计与演进大纲(如何从C语言一步步成长为C++)
c语言·开发语言·c++·c++历史·c++演进
Evand J3 小时前
【MATLAB例程,图像降噪滤波9】自适应维纳滑动窗口滤波(Wiener)图像降噪、方法对比,有中文注释
开发语言·图像处理·计算机视觉·matlab·滑动窗口·滤波·降噪
杜大哥4 小时前
python程序:如何查看电脑【电池电量的剩余百分比】 和 【是否插入连接着充电器】?
开发语言·python
wuyk5554 小时前
Python网络爬虫入门到实战 第01章:爬虫到底是什么?原理、流程、合法性、风险全解析(零基础必看)
开发语言·爬虫·python