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

回顾一下Qt的多线程技术以及实际开发常用场景

在 Qt 中,多线程编程是一项重要的技术,它允许程序同时执行多个任务,从而提高程序的性能和响应能力。下面将详细介绍 Qt 中的多线程编程,包括相关类、使用方法以及实际运用场景例子。

1. Qt 中多线程编程的相关类

QThread

QThread 是 Qt 中用于创建和管理线程的核心类。通过继承 QThread 并重写其 run() 方法,可以在新线程中执行自定义的任务。以下是一个简单的示例:

#include <QThread>
#include <QDebug>

class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = nullptr) : QThread(parent) {}

protected:
    void run() override {
        for (int i = 0; i < 5; ++i) {
            qDebug() << "Thread ID:" << QThread::currentThreadId() << "Count:" << i;
            QThread::sleep(1);
        }
    }
};

在上述代码中,MyThread 类继承自 QThread,并重写了 run() 方法。在 run() 方法中,线程会每隔 1 秒输出一次当前线程的 ID 和计数。

QRunnable 和 QThreadPool

QRunnable 是一个抽象基类,用于表示可以在线程池中运行的任务。QThreadPool 是 Qt 提供的线程池类,它可以管理和复用线程,减少线程创建和销毁的开销。以下是一个使用 QRunnable 和 QThreadPool 的示例:

#include <QRunnable>
#include <QThreadPool>
#include <QDebug>

class MyRunnable : public QRunnable
{
public:
    void run() override {
        for (int i = 0; i < 3; ++i) {
            qDebug() << "Thread ID:" << QThread::currentThreadId() << "Count:" << i;
            QThread::sleep(1);
        }
    }
};

// 使用示例
void useThreadPool() {
    QThreadPool pool;
    MyRunnable *runnable = new MyRunnable();
    runnable->setAutoDelete(true); // 任务执行完后自动删除
    pool.start(runnable);
    pool.waitForDone(); // 等待所有任务完成
}

在上述代码中,MyRunnable 类继承自 QRunnable,并重写了 run() 方法。QThreadPool 会自动分配线程来执行 MyRunnable 任务。

2. 线程间通信

在多线程编程中,线程间通信是非常重要的。Qt 提供了信号和槽机制来实现线程间的安全通信。以下是一个示例:

#include <QThread>
#include <QObject>
#include <QDebug>

// 工作线程类
class Worker : public QObject
{
    Q_OBJECT
public:
    explicit Worker(QObject *parent = nullptr) : QObject(parent) {}

signals:
    void resultReady(const QString &result);

public slots:
    void doWork() {
        QString result = "Work done";
        emit resultReady(result);
    }
};

// 主线程类
class Controller : public QObject
{
    Q_OBJECT
public:
    explicit Controller(QObject *parent = nullptr) : QObject(parent) {
        worker = new Worker();
        thread = new QThread();
        worker->moveToThread(thread);

        connect(thread, &QThread::started, worker, &Worker::doWork);
        connect(worker, &Worker::resultReady, this, &Controller::handleResults);
        connect(worker, &Worker::resultReady, thread, &QThread::quit);
        connect(worker, &Worker::resultReady, worker, &Worker::deleteLater);
        connect(thread, &QThread::finished, thread, &QThread::deleteLater);

        thread->start();
    }

public slots:
    void handleResults(const QString &result) {
        qDebug() << "Received result:" << result;
    }

private:
    Worker *worker;
    QThread *thread;
};

在上述代码中,Worker 类在新线程中执行任务,并通过信号 resultReady 向主线程发送结果。Controller 类负责管理线程和接收结果。

3. 实际运用场景例子

网络请求

在开发网络应用程序时,网络请求可能会阻塞主线程,导致界面卡顿。使用多线程可以将网络请求放在新线程中执行,避免阻塞主线程。以下是一个简单的示例:

#include <QThread>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QDebug>

class NetworkWorker : public QObject
{
    Q_OBJECT
public:
    explicit NetworkWorker(QObject *parent = nullptr) : QObject(parent) {
        manager = new QNetworkAccessManager(this);
        connect(manager, &QNetworkAccessManager::finished, this, &NetworkWorker::handleNetworkReply);
    }

signals:
    void networkDataReceived(const QByteArray &data);

public slots:
    void performNetworkRequest(const QUrl &url) {
        QNetworkRequest request(url);
        manager->get(request);
    }

private slots:
    void handleNetworkReply(QNetworkReply *reply) {
        if (reply->error() == QNetworkReply::NoError) {
            QByteArray data = reply->readAll();
            emit networkDataReceived(data);
        } else {
            qDebug() << "Network error:" << reply->errorString();
        }
        reply->deleteLater();
    }

private:
    QNetworkAccessManager *manager;
};

// 使用示例
void performNetworkTask() {
    NetworkWorker *worker = new NetworkWorker();
    QThread *thread = new QThread();
    worker->moveToThread(thread);

    connect(thread, &QThread::started, [worker]() {
        worker->performNetworkRequest(QUrl("https://www.example.com"));
    });
    connect(worker, &NetworkWorker::networkDataReceived, [](const QByteArray &data) {
        qDebug() << "Received data:" << data;
    });
    connect(worker, &NetworkWorker::networkDataReceived, thread, &QThread::quit);
    connect(worker, &NetworkWorker::networkDataReceived, worker, &NetworkWorker::deleteLater);
    connect(thread, &QThread::finished, thread, &QThread::deleteLater);

    thread->start();
}

在上述代码中,NetworkWorker 类在新线程中执行网络请求,并通过信号 networkDataReceived 将请求结果发送给主线程。

大数据处理

在处理大量数据时,如文件读写、图像处理等,可能会消耗大量的时间。使用多线程可以将数据处理任务分配到多个线程中并行执行,提高处理效率。以下是一个简单的文件读取示例:

#include <QThread>
#include <QFile>
#include <QTextStream>
#include <QDebug>

class FileReader : public QObject
{
    Q_OBJECT
public:
    explicit FileReader(QObject *parent = nullptr) : QObject(parent) {}

signals:
    void fileReadFinished(const QString &content);

public slots:
    void readFile(const QString &fileName) {
        QFile file(fileName);
        if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            QTextStream in(&file);
            QString content = in.readAll();
            file.close();
            emit fileReadFinished(content);
        } else {
            qDebug() << "Failed to open file:" << fileName;
        }
    }
};

// 使用示例
void performFileReadTask() {
    FileReader *reader = new FileReader();
    QThread *thread = new QThread();
    reader->moveToThread(thread);

    connect(thread, &QThread::started, [reader]() {
        reader->readFile("test.txt");
    });
    connect(reader, &FileReader::fileReadFinished, [](const QString &content) {
        qDebug() << "File content:" << content;
    });
    connect(reader, &FileReader::fileReadFinished, thread, &QThread::quit);
    connect(reader, &FileReader::fileReadFinished, reader, &FileReader::deleteLater);
    connect(thread, &QThread::finished, thread, &QThread::deleteLater);

    thread->start();
}

在上述代码中,FileReader 类在新线程中读取文件内容,并通过信号 fileReadFinished 将文件内容发送给主线程。


http://www.kler.cn/a/583124.html

相关文章:

  • 2025年信创国产化鸿蒙的发展趋势有哪些?
  • Redisson分布式锁实现原理
  • stm32第四天控制蜂鸣器
  • Vue中vfor循环创建DOM时Key的理解之Vue中的diff算法
  • JVM中是如何定位一个对象的
  • 学习计划:第四阶段(第十周)
  • 从Swish到SwiGLU:激活函数的进化与革命,qwen2.5应用的激活函数
  • 嵌入式八股C语言---面向对象篇
  • 以数学建模视角打开软件测试:理论+实战全解析!
  • golang从入门到做牛马:第十六篇-Go语言`range`:循环遍历的“瑞士军刀”
  • ffmpeg打开麦克风,录制音频并重采样
  • 【蓝桥杯—单片机】第十五届省赛真题代码题解析 | 思路整理
  • Microsoft Dragon Copilot:医疗AI革命开启,用语音终结手写病历时代
  • 【Leetcode 每日一题】2012. 数组美丽值求和
  • java 手搓一个http工具类请求传body
  • emacs使用mongosh的方便工具发布
  • 练习:关于静态路由,手工汇总,路由黑洞,缺省路由相关
  • [GHCTF 2025]UPUPUP【.htaccess绕过 XBM/WBMP】
  • 面试题(1)MySQL中的锁
  • UVC摄像头命令推流,推到rv1126里面去