Qt线程QThread详解

Qt线程QThread详解本文介绍了 Qt 框架中的 QThread 类 用于管理和控制线程

大家好,欢迎来到IT知识分享网。

前言

在这里插入图片描述
在程序中使用线程可以提高程序的性能、并发性、响应性和稳定性,使得程序设计更加灵活和简单。但是,线程编程也有一些挑战,如线程安全性和死锁等问题需要格外注意。我们使用QT框架编程时,可以用框架提供的线程类QThread来管理线程。本文将介绍使用QThread编程时的两种方式,并给出一个数据同步的示例。

1.QThread介绍

QThread的主要优点是简单易用,能轻松地创建和管理线程。它提供了一些方法来控制线程的生命周期,包括start()和quit()方法来启动和停止线程,以及wait()方法来等待线程完成。

QThread还提供了一些信号来管理线程。例如,finished()信号在线程完成执行后发出,error()信号在线程发生错误时发出。

2.QThread示例一

在这个示例中有两个自定义线程:IncrementThread和DoubleThread,它们分别用于增加数字和将数字乘以2。这些线程都使用QThread类,并且都包含一个信号,以便在线程运行时向主线程发送结果。

#include <QObject> #include <QThread> #include <QVector> class IncrementThread : public QThread { 
    Q_OBJECT public: IncrementThread(int count) : count(count) { 
   } signals: void countChanged(int count); protected: void run() { 
    for (int i = 1; i <= count; ++i) { 
    emit countChanged(i); msleep(1000); } } private: int count; }; class DoubleThread : public QThread { 
    Q_OBJECT public: DoubleThread(const QVector<int>& nums) : nums(nums) { 
   } signals: void doubled(int num); protected: void run() { 
    for (int num : nums) { 
    emit doubled(num * 2); msleep(1000); } } private: QVector<int> nums; }; 

在MainWindow类中,我们将创建线程,并将它们的信号连接到槽函数onCountChanged和onDoubled中。每当IncrementThread发出onCountChanged信号时,onDoubled将在主线程中更新标签的文本,以显示当前进度。类似地,每当DoubleThread发出doubled信号时,onDoubled将在主线程中更新标签的文本,以显示结果。

我们在构造函数中创建这两个线程,将它们的信号连接到槽函数中,并启动线程。

#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); ui->label->setText("Waiting for results..."); incrementThread = new IncrementThread(5); doubleThread = new DoubleThread({ 
   1, 2, 3, 4, 5}); connect(incrementThread, &IncrementThread::countChanged, this, &MainWindow::onCountChanged); connect(doubleThread, &DoubleThread::doubled, this, &MainWindow::onDoubled); incrementThread->start(); doubleThread->start(); } void MainWindow::onCountChanged(int count) { 
    ui->label->setText(QString("Incrementing %1").arg(count)); qDebug() << "Incrementing " << count; } void MainWindow::onDoubled(int num) { 
    ui->label->setText(QString("Doubling %1").arg(num)); qDebug() << "Doubling " << num; } MainWindow::~MainWindow() { 
    delete ui; } 

3.QThread示例二

在这个示例中,我们创建了一个Worker类,该类包含一个doWork槽函数,用于在新线程中执行任务。在main函数中,我们创建了一个新的QThread对象和一个Worker对象,并将Worker对象的doWork槽函数连接到QThread对象的started信号上。然后,我们将Worker对象通过moveThread()方法移动到新线程中,并启动新线程。在主线程中,我们也有一个类似的循环,用于展示主线程和新线程是同时执行的。在循环结束后,我们调用了quit函数,以停止新线程的事件循环,并使用wait函数等待线程完成。

#include <QCoreApplication> #include <QThread> #include <QDebug> #include <chrono> class Worker : public QObject { 
    Q_OBJECT public: Worker(int num_iterations) : m_num_iterations(num_iterations) { 
   } public slots: void doWork() { 
    for (int i = 0; i < m_num_iterations; i++) { 
    qDebug() << "Thread function is running..."; QThread::msleep(1000); } } private: int m_num_iterations; }; int main(int argc, char *argv[]) { 
    QCoreApplication a(argc, argv); int num_iterations = 5; QThread thread; Worker worker(num_iterations); //把线程启动信号与worker的doWork槽函数绑定在一起 QObject::connect(&thread, &QThread::started, &worker, &Worker::doWork); //将woker对象移动到thread线程中执行 worker.moveToThread(&thread); thread.start(); for (int i = 0; i < num_iterations; i++) { 
    qDebug() << "Main thread is running..."; QThread::msleep(500); } thread.quit(); thread.wait(); return a.exec(); } 

注意,若调用moveToThread()方法将worker对象移动到某个线程,则worker不能指定parent指针。默认情况下,对象是在哪个线程创建的,就属于哪个线程。

4.线程同步

在这个示例中,我们将创建一个线程并在其中使用QWaitCondition和QMutex来实现线程同步。

#include <QThread> #include <QWaitCondition> #include <QMutex> #include <QDebug> class MyThread : public QThread { 
    public: void run() override { 
    //加锁 QMutexLocker locker(&mutex); qDebug() << "Thread started"; // Do some work here qDebug() << "Thread waiting"; //线程挂起,直到调用wakeUp函数后,继续往下执行 condition.wait(&mutex); qDebug() << "Thread resumed"; // Do more work here qDebug() << "Thread finished"; } void wakeUp() { 
    QMutexLocker locker(&mutex); condition.wakeOne(); } private: QWaitCondition condition; QMutex mutex; }; int main(int argc, char *argv[]) { 
    MyThread thread; thread.start(); // Do some other work here thread.wakeUp(); thread.wait(); return 0; } 

在这个示例中,我们创建了一个MyThread类,继承自QThread,重写了run()函数,在其中执行一些工作。在该函数中,我们获取了一个QMutexLocker对象,以确保线程同步,并输出一些信息来显示线程已启动。

然后,我们调用QWaitCondition的wait()方法,将线程挂起,直到其他线程调用了wakeUp()方法。在等待期间,我们释放了QMutexLocker,以允许其他线程对共享资源进行访问。

在wakeUp()方法中,我们获取了QMutexLocker对象,以确保线程同步,并调用QWaitCondition的wakeOne()方法,以唤醒一个挂起的线程。

在主线程中,我们创建了一个MyThread对象并调用start()方法来启动线程。然后,我们执行一些其他工作,并在最后调用wakeUp()方法来唤醒线程。最后,我们调用wait()方法等待线程完成。

这个示例演示了如何使用QWaitCondition和QMutex来实现线程同步。QWaitCondition用于等待线程唤醒,而QMutex用于保护共享资源并防止竞争条件。通过使用这些类,我们可以编写线程安全的代码,并避免死锁和竞争条件的问题。

以上就是本文的全部内容了,希望对大家有帮助,如有问题,欢迎指正!

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/121726.html

(0)
上一篇 2025-10-21 20:33
下一篇 2025-10-21 20:45

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信