欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 产业 > QT(多线程)

QT(多线程)

2025/3/13 13:15:39 来源:https://blog.csdn.net/weixin_58038211/article/details/143244135  浏览:    关键词:QT(多线程)

一个应用程序一般只有一个线程,一个线程内的操作是顺序执行的,如果有某个比较消耗时间的计算或操作,比如网络通信中的文件传输,在一个线程内操作时,用户界面就可能会冻结而不能及时响应。这种情况下,可以创建一个单独的线程来执行比较消耗时间的操作,并与主线程之间处理好同步与数据交互,这就是多线程应用程序。

QThread 类功能简介

QThread 是线程类,是实现多线程操作的核心类,一般从 QThread 继承定义自己的线程类。

Qt提供了 QMutex、QMutexLocker、QReadWriteLock、QwaitCondition、QSemaphore 等多种类用于实现线程之间的同步。

QThread类提供不依赖于平台的管理线程的方法。一个QThread 类的对象管理一个线程,一般从 QThread 继承一个自定义类,并重定义虚函数run0,在run()函数里实现线程需要完成的任务。

将应用程序的线程称为主线程,额外创建的线程称为工作线程。

一般在主线程里创建工作线程,并调用 start(开始执行工作线程的任务。start()会在内部调用run()函数,进入工作线程的事件循环,在 run()函数里调用 exit()或 quit()可以结束线程的事件循环,或在主线程里调用terminate()强制结束线程。

概述图:

  • 主线程内有很多方法在主线程内, 但是子线程,只有 run()方法是在子线程里的。

  • run()方法是继承于 QThread 类的方法,用户需要重写这个方法,一般是把耗时的操作写在这个 run()方法里面。

QThread 类的主要接口

公共函数:

  • bool isFinished(): 线程是否结束。
  • bool isRunning(): 线程是否正在运行。
  • Priority priority(): 返回线程的优先级。
  • void setPriority (Priority priority): 设置线程的优先级。
  • void exit(int returnCode = 0): 退出线程的事件循环,退出码为returnCode,0表示成功退出;否则表示有错误。
  • bool wait(unsigned long time ): 阻止线程执行,直到线程结束(从run()函数返回),或等待时间超过time 毫秒。

公共槽函数:

  • void quit(): 退出线程的事件循环,并返回代码0,等效于exit(0)。
  • void start(Priority priority )内部调用run()开始执行线程,操作系统根据priority参数进行调度终止线程的运行,但不是立即结束线程,而是等待操作系统结束线程。
  • void terminate(): 使用 terminate()之后应使用 wait()。

信号:

  • void finished(): 在线程就要结束时发射此信号。
  • void started(): 在线程开始执行、run()函数被调用之前发射此信号。

静态公共成员:

  • int idealThreadCount(): 返回系统上能运行的线程的理想个数。
  • void msleep(unsigned long msecs): 强制当前线程休眠msecs 毫秒。
  • void sleep(unsigned long secs): 强制当前线程休眠 secs 秒。
  • void usleep(unsigned long usecs): 强制当前线程休眠 usecs 微秒。

保护函数:

  • virtual void run():start()调用run()函数开始线程任务的执行,所以在run()函数里实现线程的任务功能。
  • int exec(): 由run()函数调用,进入线程的事件循环,等待exit()退出。

一、QThread 线程

点击按钮生成一个线程示例:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QThread>
#include <QDebug>
#include <QPushButton>class WorkerThread; //声明工作线程类class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private:WorkerThread *workerThread; //实例化线程对象QPushButton *pushButton;//槽函数
private slots:void handleResults(const QString &result); void pushButtonClicked();
};
#endif // MAINWINDOW_H//定义工作线程类
class WorkerThread : public QThread
{Q_OBJECT
public:WorkerThread(QWidget *parent = nullptr) {Q_UNUSED(parent);}//start() 线程开始会调用这个函数void run() override {QString result = "thread open success !";sleep(1);emit resultReady(result); //emit 发送信号}
signals:void resultReady(const QString &s); 
};

mainwindow.c

#include "mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{this->setGeometry(0, 0, 800, 480);pushButton = new QPushButton(this);workerThread = new WorkerThread(this);pushButton->resize(100, 40);pushButton->setText("open thread !");connect(workerThread, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));connect(pushButton, SIGNAL(clicked()), this, SLOT(pushButtonClicked()));
}//析构函数 关闭窗口时候调用
MainWindow::~MainWindow()
{workerThread->quit();if (workerThread->wait(2000)) {qDebug() << "thread end !" << endl;}
}void MainWindow::handleResults(const QString &result) {qDebug()<< result << endl;
}void MainWindow::pushButtonClicked() {if (!workerThread->isRunning()) {workerThread->start();}
}

注:emit 是用于发送信号(signal)的关键字。当一个信号被发送时,所有与该信号关联的槽(slot)函数都会被调用。

二、继承 QObject 的线程

继承 QObject 类更加灵活。 它通过 QObject::moveToThread()方法,将一个 QObeject
的类转移到一个线程里执行。

概述图:


写一个类继承 QObject,通过 QObject::moveToThread()方法将它移到一个 QThread 线程里执行。

示例描述:按钮1开启一个线程, 按钮2开启另一个线程, 按钮3关闭所有线程

运行图

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QThread>
#include <QDebug>
#include <QPushButton>class Worker;class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();public:QPushButton *button1;QPushButton *button2;QPushButton *button3;QThread *thread1;QThread *thread2;Worker *worker1;Worker *worker2;public slots:void startThread1();void startThread2();void stopAllThreads();signals:void startWork1(const QString &);void startWork2(const QString &);};class Worker:public QObject {Q_OBJECTpublic:Worker() : m_stop(false) {} //初始化m_stoppublic slots:void doWork() {qDebug() << "线程开始运行:" << QThread::currentThread();while (!m_stop) {QThread::sleep(1);  // 模拟耗时操作qDebug() << "正在处理任务:" << QThread::currentThread();}qDebug() << "线程停止运行:" << QThread::currentThread();}void stopWork() {m_stop = true;}public:bool m_stop;};#endif // MAINWINDOW_H

mainwindow.c

#include "mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{this->setGeometry(0, 0, 800, 480);// 创建按钮button1 = new QPushButton("开启线程一", this);button2 = new QPushButton("开启线程二", this);button3 = new QPushButton("关闭所有线程", this);button1->setGeometry(300, 200, 80, 40);button2->setGeometry(400, 200, 80, 40);button3->setGeometry(500, 200, 100, 40);// 创建线程和工作对象thread1 = new QThread(this);thread2 = new QThread(this);worker1 = new Worker();worker2 = new Worker();worker1->moveToThread(thread1);worker2->moveToThread(thread2);// 连接信号和槽,控制线程启动connect(button1, &QPushButton::clicked, this, &MainWindow::startThread1);connect(button2, &QPushButton::clicked, this, &MainWindow::startThread2);connect(button3, &QPushButton::clicked, this, &MainWindow::stopAllThreads);// 连接线程启动信号到 worker 的任务槽connect(thread1, &QThread::started, worker1, &Worker::doWork);connect(thread2, &QThread::started, worker2, &Worker::doWork);// 在线程结束时,自动删除 worker 对象connect(thread1, &QThread::finished, worker1, &Worker::deleteLater);connect(thread2, &QThread::finished, worker2, &Worker::deleteLater);
}MainWindow::~MainWindow() {
}void MainWindow::startThread1() {if (!thread1->isRunning()) {worker1->m_stop = false;  // 重置停止标志thread1->start();qDebug() << "启动线程一";}
}void MainWindow::startThread2() {if (!thread2->isRunning()) {worker2->m_stop = false;  // 重置停止标志thread2->start();qDebug() << "启动线程二";}
}void MainWindow::stopAllThreads() {// 停止 worker 的工作worker1->stopWork();worker2->stopWork();// 等待线程完成并退出if (thread1->isRunning()) {thread1->quit();thread1->wait();}if (thread2->isRunning()) {thread2->quit();thread2->wait();}qDebug() << "所有线程已关闭";
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词