Qt中使用多线程并返回结果到主线程的例子

Qt中使用多线程是通过connect关联信号和槽来实现子线程与主线程之间的数据传递与页面数据展示的,详细请看下面实例:
下面三行代码是实现主线程与子线程通信的信号连接。

//子线程运行了RUN()中的retrun之后会发出finished信号,来执行子线程中QObject::deleteLater方法
connect(&workerThread1, &QThread::finished, worker, &QObject::deleteLater);

//主线程发射信号子线程执行槽函数用于在子线程中进行处理运算
connect(this, &MainWindow::operate, worker, &Worker::doWork);

//子线程发射信号主线程执行槽函数用于在主线程中返回执行结果
connect(worker, &Worker::resultReady, this, &MainWindow::handleResults);

mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QDateTime>

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

    //子线程1
    Worker *worker = new Worker;
    worker->moveToThread(&workerThread1);
    connect(&workerThread1, &QThread::finished, worker, &QObject::deleteLater);
    connect(this, &MainWindow::operate, worker, &Worker::doWork);
    connect(worker, &Worker::resultReady, this, &MainWindow::handleResults);
    workerThread1.start();

    //子线程2
    Worker *worker2 = new Worker;
    worker2->moveToThread(&workerThread2);
    connect(&workerThread2, &QThread::finished, worker2, &QObject::deleteLater);
    connect(this, &MainWindow::operate2, worker2, &Worker::doWork2);//关联主线程与子线程的信号和槽
    connect(worker2, &Worker::resultReady2, this, &MainWindow::handleResults2);//关联子线程与主线程的信号和槽
    workerThread2.start();
}

MainWindow::~MainWindow()
{
    delete ui;
    workerThread1.quit();
    workerThread1.wait();

    workerThread2.quit();
    workerThread2.wait();


}
void MainWindow::handleResults(const QString &str)
{
    ui->lineEdit->setText(str);
    qDebug()<<"MainWindow::handleResults收到的内容是:"<<str<<endl;

}
void MainWindow::handleResults2(const QString &str)
{
    ui->lineEdit_2->setText(str);
    qDebug()<<"MainWindow::handleResults2收到的内容是:"<<str<<endl;

}
void Worker::doWork(const QString &str) {

    qDebug()<<"收到的内容是:"<<str<<endl;
    emit resultReady(str);//在子线程中发射信号,驱动主线程的槽函数
}
void Worker::doWork2(const QString &str) {

    qDebug()<<"收到的内容是:"<<str<<endl;
    emit resultReady2(str);//在子线程中发射信号,驱动主线程的槽函数
}
void MainWindow::on_pushButton_clicked()
{
    emit operate(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")+"进程1发射了信号!");//在主线程中发射信号,驱动子线程的槽函数,在子线程中做大量逻辑处理
    emit operate2(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")+"进程2发射了信号!");//在主线程中发射信号,驱动子线程的槽函数,在子线程中做大量逻辑处理
}

mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QThread>
#include <QObject>
#include <QThread>

class Worker : public QObject
  {
      Q_OBJECT
  public slots:
      void doWork(const QString &str);
      void doWork2(const QString &str);
  signals:
      void resultReady(const QString &result);
      void resultReady2(const QString &result);
  };
QT_BEGIN_NAMESPACE
namespace Ui {
    class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
    Q_OBJECT
    QThread workerThread1;
    QThread workerThread2;
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private slots:
    void on_pushButton_clicked();
    void handleResults(const QString &str);
    void handleResults2(const QString &str);
signals:
    void operate(const QString &str);
    void operate2(const QString &str);
private:
    Ui::MainWindow *ui;
};
#endif

main.cpp

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

秋风写于淄博,业务联系与技术交流:Q375172665

<think>好的,用户想要了解Qt使用多线程例子。首先,我需要确定用户对Qt多线程的基础了解程度。可能他们有一定的C++基础,但对Qt的线程机制不太熟悉。Qt中常用的多线程方法有两种:QThread子类化和使用QObject配合moveToThread。我应该分别介绍这两种方法,给出具体的例子,方便用户理解。 首先,QThread子类化是比较传统的方式,用户可能更容易理解继承的概念。需要说明重写run()方法,注意不要在该方法中直接操作UI,因为会导致界面卡顿。同时,需要提醒线程安全的问题,比如使用信号槽进行跨线程通信。 接下来,使用QObject和moveToThread的方法更符合Qt的事件驱动模型。这种方法将工作对象移动到新线程,通过信号槽触发任务。这种方式更灵活,适合需要频繁启停任务的场景。需要详细说明如何创建Worker类,定义信号和槽,以及如何正确连接信号和槽,确保任务在子线程中执行。 另外,用户可能对线程间的通信和同步感兴趣,比如如何传递数据,如何避免竞态条件。可以提到Qt的信号槽机制自动是线程安全的,推荐使用它们进行通信,而不是直接调用跨线程的方法。同时,可以简要介绍QMutex、QWaitCondition等同步工具,但可能在基础例子中不需要深入,保持简单。 还需要注意错误处理,比如线程崩溃或长时间不响应的情况。提醒用户避免在子线程中操作GUI组件,应该通过信号更新UI。同时,在例子中加入错误处理的注释,帮助用户养成良好的编程习惯。 最后,总结两种方法的优缺点,帮助用户根据具体需求选择合适的多线程实现方式。可能用户需要处理耗时任务,比如文件操作、网络请求等,正确的多线程使用能提升应用性能。确保示例代码结构清晰,注释详细,便于用户复制和测试。</think>以下是一个Qt多线程的典型示例及分步说明,采用两种常用方法实现: ▌方法一:继承QThread类 ```cpp // 1. 自定义线程类 class WorkerThread : public QThread { Q_OBJECT protected: void run() override { // 耗时操作(注意:不要在此操作UI) for(int i=0; i<5; ++i){ QThread::sleep(1); emit progressUpdated(i+1); // 通过信号更新进度 } } signals: void progressUpdated(int value); }; // 2. 使用线程 void MainWindow::startTask(){ WorkerThread *thread = new WorkerThread(this); connect(thread, &WorkerThread::progressUpdated, this, &MainWindow::updateProgress); // 连接信号到UI更新槽 connect(thread, &WorkerThread::finished, thread, &QObject::deleteLater); // 自动释放内存 thread->start(); // 启动线程 } ``` ▌方法二:使用QObject+moveToThread(推荐方式) ```cpp // 1. 创建工作类 class Worker : public QObject { Q_OBJECT public slots: void doWork(){ for(int i=0; i<5; ++i){ QThread::sleep(1); emit progress(i*20); // 发送进度信号 } emit finished(); } signals: void progress(int percent); void finished(); }; // 2. 线程管理 void MainWindow::startAdvancedTask(){ QThread *thread = new QThread(this); Worker *worker = new Worker(); worker->moveToThread(thread); // 关键步骤:移动对象到新线程 connect(thread, &QThread::started, worker, &Worker::doWork); connect(worker, &Worker::progress, this, &MainWindow::updateProgress); connect(worker, &Worker::finished, thread, &QThread::quit); connect(thread, &QThread::finished, worker, &QObject::deleteLater); connect(thread, &QThread::finished, thread, &QObject::deleteLater); thread->start(); } ``` ▶ 关键注意事项: 1. **线程安全**: - 使用`QMetaObject::invokeMethod`或信号槽进行跨线程通信 - 共享数据需用`QMutex`保护 ```cpp QMutex mutex; void safeOperation(){ QMutexLocker locker(&mutex); // 安全操作共享资源 } ``` 2. **信号槽连接类型**: ```cpp connect(sender, &Sender::signal, receiver, &Receiver::slot, Qt::AutoConnection); // 默认自动检测线程关系 ``` 3. **定时器替代方案**: 对于简单异步操作,可用`QTimer::singleShot` ```cpp QTimer::singleShot(0, [](){ // 在事件循环中延迟执行 }); ``` ▶ 两种方法的对比: | 特性 | 继承QThread | moveToThread方式 | |--------------------|---------------------|---------------------| | 代码结构 | 继承体系 | 组合方式 | | 任务生命周期 | 线程启动即执行 | 通过信号触发 | | 适用场景 | 简单单次任务 | 复杂/重复任务 | | 资源管理 | 需手动释放 | 自动回收更安全 | ▶ 最佳实践建议: 1. 耗时操作(文件处理、网络请求等)必须放在子线程 2. 主线程只处理UI更新 3. 使用`QThreadPool`+`QRunnable`处理短期任务 4. 调试时使用`qDebug() << QThread::currentThreadId()` 通过合理使用多线程,可以显著提升Qt程序的响应速度。建议优先选择`moveToThread`方式,因其更符合Qt的事件驱动设计理念,能更好地管理对象生命周期。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值