Qt 多线程(QThread)

article/2025/10/27 17:01:21

Qt 多线程(QThread)

一.理解QThread

关于QThread,参考qt助手中的解析

Detailed Description
A QThread object manages one thread of control within the program. QThreads begin executing in run(). By default, run() starts the event loop by calling exec() and runs a Qt event loop inside the thread.
You can use worker objects by moving them to the thread using QObject::moveToThread().
(详细说明
QThread对象管理程序中的一个控制线程。QThreads开始在run()中执行。默认情况下,run()通过调用exec()启动事件循环,并在线程内运行Qt事件循环。
您可以通过使用QObject::moveToThread()将辅助对象移动到线程来使用它们。)

注意:实际上,QThread可以理解为线程控制器,它本身并不是一个线程,只是QThread管理了一个线程而已。
实际上,继承自QThread的类中,下面两种情况的代码才是运行在次线程中。
(1).run()函数的代码。
(2).次线程执行exec()函数,开启事件循环。某个继承自QObject的类obj,通过moveToThread()函数移入次线程,
并且通过信号槽机制触发obj的槽函数(信号槽连接方式不能为 Qt::DirectConnection)

二.QThread的使用方法。

方法1新建一个类,继承类QThread,重载run()函数,并将关键代码放到run()中执行。执行完成后,发送信号,告诉主线程完成

//workerthread.h

#ifndef WORKERTHREAD_H
#define WORKERTHREAD_H
#include <QThread>class WorkerThread : public QThread
{Q_OBJECTpublic:WorkerThread(QObject *parent = nullptr);protected:void run();signals:void sigResult();
};#endif // WORKERTHREAD_H

//workerthread.cpp

#include "workerthread.h"
#include <QDebug>WorkerThread::WorkerThread(QObject *parent):QThread(parent)
{}void WorkerThread::run()
{/*死循环,让线程一直跑。或者处理完毕就退出*/qDebug()<<"WorkerThread run: threadId: "<<QThread::currentThreadId();emit sigResult();
}

//mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include "myThread1.h"QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private:Ui::MainWindow *ui;private slots:void slotResult();void slotResultQueued();void slotResultDirect();};
#endif // MAINWINDOW_H

//mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>
#include <QDebug>
#include <workerthread.h>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);qDebug()<<"main threadId: "<<QThread::currentThreadId();WorkerThread *workthread = new WorkerThread(this);//匿名槽函数,槽函数运行在次线程connect(workthread, &WorkerThread::sigResult, [=](){qDebug()<<"lanba slot threadId: "<<QThread::currentThreadId();});//普通连接方式,槽函数运行在主线程connect(workthread, &WorkerThread::sigResult, this, &MainWindow::slotResult);//队列连接connect(workthread, &WorkerThread::sigResult, this, &MainWindow::slotResultQueued, Qt::QueuedConnection);//直接连接connect(workthread, &WorkerThread::sigResult, this, &MainWindow::slotResultDirect, Qt::DirectConnection);workthread->start();
}MainWindow::~MainWindow()
{delete ui;
}//普通连接方式的槽函数
void MainWindow::slotResult()
{qDebug()<<"slotResult threadId: "<<QThread::currentThreadId();
}//队列连接方式的槽函数
void MainWindow::slotResultQueued()
{qDebug()<<"slotResultQueued threadId: "<<QThread::currentThreadId();
}//直接连接方式的槽函数
void MainWindow::slotResultDirect()
{qDebug()<<"slotResultDirect threadId: "<<QThread::currentThreadId();
}

运行结果:
在这里插入图片描述
结论:
使用上述方式调用线程槽函数所在的线程如下:
1.槽函数为匿名函数,槽函数运行在发送者所在的线程。
2.采用Qt::DirectConnection方式连接信号槽,槽函数运行在发送者所在的线程。
3.其它连接方式,槽函数运行在接受者所在的线程。

方法2:次线程在run()函数中执行exec()函数,开启事件循环。某个继承自QObject的类obj,通过moveToThread()函数移入次线程,
并且通过信号槽机制触发obj的槽函数(信号槽连接方式不能为 Qt::DirectConnection)

//workerThread.h

#ifndef WORKERTHREAD_H
#define WORKERTHREAD_H
#include <QThread>class WorkerThread : public QThread
{Q_OBJECTpublic:WorkerThread(QObject *parent = nullptr);protected:void run();
};

//workerThread.cpp

#include "workerthread.h"
#include <QDebug>WorkerThread::WorkerThread(QObject *parent):QThread(parent)
{}void WorkerThread::run()
{qDebug()<<"WorkerThread run: threadId: "<<QThread::currentThreadId();exec();		//执行exec()函数,开启事件循环
}

//worker.h

#ifndef WORKER_H
#define WORKER_H#include <QObject>class Worker : public QObject
{Q_OBJECTpublic:explicit Worker(QObject *parent = nullptr);signals:void sigFinished();public slots:void doSomething();
};#endif // WORKER_H

//worker.cpp

#include "worker.h"
#include <QThread>
#include <QDebug>Worker::Worker(QObject *parent) :QObject(parent)
{}void Worker::doSomething()
{qDebug()<<"worker doSomething: threadId: "<<QThread::currentThreadId();emit sigFinished();
}

//mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include "myThread1.h"QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private:Ui::MainWindow *ui;signals:void sigDoSomething();private slots:void slotFinished();void slotFinishedQueued();void slotFinishedDirect();};
#endif // MAINWINDOW_H

//mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>
#include <QDebug>
#include <workerthread.h>
#include <worker.h>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);qDebug()<<"main threadId: "<<QThread::currentThreadId();WorkerThread *workthread = new WorkerThread(this);Worker *worker = new Worker();      //不能设置父类worker->moveToThread(workthread);   //将worker 移动到 次线程//主线程发送信号,次线程接收信号,槽函数运行在接受者线程。connect(this, &MainWindow::sigDoSomething, worker, &Worker::doSomething);//匿名函数connect(worker, &Worker::sigFinished, [=](){qDebug()<<"lanba slot threadId: "<<QThread::currentThreadId();});//普通连接方式,槽函数运行在接受者线程connect(worker, &Worker::sigFinished, this, &MainWindow::slotFinished);//队列连接,槽函数运行在接受者线程connect(worker, &Worker::sigFinished, this, &MainWindow::slotFinishedQueued, Qt::QueuedConnection);//直接连接,槽函数运行在发送者所在线程。connect(worker, &Worker::sigFinished, this, &MainWindow::slotFinishedDirect, Qt::DirectConnection);workthread->start();emit sigDoSomething();}MainWindow::~MainWindow()
{delete ui;
}//普通连接方式的槽函数
void MainWindow::slotFinished()
{qDebug()<<"slotFinished threadId: "<<QThread::currentThreadId();
}//队列连接方式的槽函数
void MainWindow::slotFinishedQueued()
{qDebug()<<"slotFinishedQueued threadId: "<<QThread::currentThreadId();
}//直接连接方式的槽函数
void MainWindow::slotFinishedDirect()
{qDebug()<<"slotFinishedDirect threadId: "<<QThread::currentThreadId();
}

//运行 结果
在这里插入图片描述
结论,通过moveToThread()方式,确实可以将槽函数运行在次线程(信号槽连接方式不能为:Qt::DirectConnection)


http://chatgpt.dhexx.cn/article/dxRHdDNb.shtml

相关文章

QT 多线程的实现方法以及GUI线程与其他线程间的通信

GUI线程 Qt应用程序exec后就会生成一个线程&#xff0c;这个线程就是主线程&#xff0c;在GUI程序中也称为GUI线程。主线程也是唯一允许创建QApplication或QCoreAppliation对象&#xff0c;比并且可以对创建的对象调用exec()的线程&#xff0c;从而进入事件循环。 在只有主线…

QT多线程接收串口数据

** QT多线程接收串口数据 ** 1.前言 QT多线程的使用&#xff0c;和绝大数人一样&#xff0c;犯了错误&#xff08;请查阅Qt开发人员( Bradley T. Hughes)Blog中的文章 you are-doing-it-wrong介绍&#xff09;。为了解决问题&#xff0c;网上查阅学习了几十篇文章&#xff0c…

Qt多线程互斥

目录 一、多线程与临界资源的依赖 现象分析 二、互斥和解决方法 三、QMutex的主要成员函数和使用 四、示例代码 五、小结 一、多线程与临界资源的依赖 除了上一节所说的&#xff0c;多线程在代码执行的时序上会有依赖&#xff0c;那么其他地方是否还有所依赖呢&#xff…

QT 多线程创建方法及应用实例

QT 多线程创建方法及应用实例 方法一&#xff1a; &#xff08;1&#xff09;创建一个QT应用 &#xff08;2&#xff09;创建线程类&#xff0c;继承QThread simplethreadone.h #ifndef SIMPLETHREADONE_H #define SIMPLETHREADONE_H #include <QThread>class SimpleThr…

Qt 多线程专栏

主线程就是进程&#xff0c;进程代表4个G的资源空间&#xff0c;主线程退出就意味着进程退出&#xff0c;在Qt中&#xff0c;主线程不能是子线程的父对象&#xff0c;因此必须在线程的析构函数中去delete线程对象。 只要定时器启动&#xff0c;自动触发timeout()信号 类A继承了…

Qt多线程编程

由于疫情原因被封控在家&#xff0c;相信大家也有跟我类似的情况&#xff0c;在学习知识提升和充实自己&#xff0c;下面我将这几天在学习的Qt多线程编程做个简单的总结&#xff0c;随此笔记的还有几个简单的例子&#xff0c;以便后续开发过程中回忆和参考。 Qt的多线程开发&am…

Qt多线程

Qt多线程有两种方法&#xff1a; 1、定义一个QThread的派生类&#xff0c;重写run函数&#xff0c;run函数中的程序就是新线程中要执行的内容。在主线程中实例化该类&#xff0c;调用start函数&#xff0c;就可以实现多线程。 2、定义一个QObject的派生类&#xff0c;把要在新线…

Qt创建多线程的两种方法

来源&#xff1a;https://github.com/czyt1988/czyBlog/tree/master/tech/QtThread 1.摘要 Qt有两种多线程的方法&#xff0c;其中一种是继承QThread的run函数&#xff0c;另外一种是把一个继承于QObject的类转移到一个Thread里。 Qt4.8之前都是使用继承QThread的run这种方法…

Qt----多线程

文章目录 多线程一、继承QThread的线程1. 应用实例2. 程序运行效果 二、继承QObject的线程1. 应用实例2. 程序运行效果 多线程 我们写的一个应用程序&#xff0c;应用程序跑起来后一般情况下只有一个线程&#xff0c;但是可能也有特殊情况。比如我们前面章节写的例程都跑起来后…

Qt5教程(九):Qt多线程

目录&#xff1a; 一、创建工程 二、QThread 源码一览 三、QThread相关方法介绍 四、创建线程 一、创建工程 先创建一个工程吧, 具体步骤前面讲过很多次了&#xff0c; 就不再细说了。 然后在Header文件夹下创建添加一个头文件, 右键Headers -> Add New... -> C -&g…

Qt 多线程的几种实现方式

Qt多线程的实现方式有&#xff1a; 1. 继承QThread类&#xff0c;重写run()方法 2. 使用moveToThread将一个继承QObject的子类移至线程&#xff0c;内部槽函数均在线程中执行 3. 使用QThreadPool,搭配QRunnable&#xff08;线程池&#xff09; 4. 使用QtConcurrent&#xf…

QT中的多线程

目录 1、QThread介绍 1.2、继承Qthread类 1.2.1、得到线程id 1.2.2、让线程一直执行 1.2.3、线程退出 1.2.4、​​​​​​​connect的第五个参数 1.2.5、线程锁 QMutex ​​​​​​​ 1、QThread介绍 QThread类提供了一个与平台无关的管理线程的方法。一个QThread对…

faild to create process解决办法

win7下运行pip时报faild to create process的解决办法&#xff1a; 1.找到python.exe文件&#xff0c;复制其文件路径。如下图&#xff0c;python.exe路径为D:\interpreter\python.exe。 2.找到pip-script.py文件&#xff0c;打开。将步骤1中复制的路径粘贴在第一行&#xff0…

CreateProcess error=2, 系统找不到指定的文件 解决方法

CreateProcess error2, 系统找不到指定的文件 解决方法 一般这是由于ndk缺少文件引起的 解决方法1&#xff1a; 在项目根目录下的local.properties文件中加cmd后缀 方法二下载16b的版本替换原来的ndk-bundle目录&#xff0c;默认在C:\Users\用户名\AppData\Local\Android\S…

SQL SERVER 2008 执行xp_cmdshell的过程中出错,调用createprocess失败,错误代码 5 解决方案

1、进入 控制面板----管理工具------本地安全策略 点击 本地策略--------安全选项 把“网络安全:LAN管理器身份验证级别”双击打开&#xff0c;选择“发送 LM 和 NTLM 响应”&#xff08;原来是“没有定义”&#xff09;。确认后&#xff0c;重新启动服务器&#xff0c;该问题…

runnerw.exe: CreateProcess failed with error 5:

在idea配置Git时遇到这个问题&#xff1a; 后来发现是我路径设置错了&#xff1a; 解决方案 修改设置里的路径即可&#xff08;Setings-Version Control-Git&#xff09;

Qt creater出现“启动程序失败,路径或者权限错误”或“The process could not be started!”解决方法

Qt creater出现“启动程序失败&#xff0c;路径或者权限错误”或“The process could not be started&#xff01;”解决方法 错误示例 远古版本的QTCreator在编译程序时没问题&#xff0c;在运行程序时会提示“The process could not be started&#xff01;" 较新版本…

failed to create process.

由于python-2.7是先出来&#xff0c;但是官方只更新到2020年1月1日&#xff1b;而python-3.6与python-2.7有一定的差别&#xff0c;会同时在电脑上安装这两个版本的python&#xff0c;为了能更好的调用python不同的版本&#xff0c;会设定一个执行时使用python2.exe&#xff0c…

CreateProcessAsUser

该CreateProcessAsUser函数创建一个新的进程及其主线程。新进程然后执行指定的可执行文件。该CreateProcessAsUser功能类似的CreateProcess函数&#xff0c;除了新进程运行在由hToken参数表示的用户的安全上下文中。默认情况下&#xff0c;新进程是非交互式的&#xff0c;即它运…

生成了文件却还是报错 Error:CreateProcess failed

想起来&#xff0c;以前用keil编译器的时候&#xff0c;也出现过这样的问题&#xff1a; 第一眼都是看到了“1 Error(s)”&#xff0c;就下意识认为自己程序出错了&#xff0c;找了半天没找到。 后来多看了一眼&#xff0c;发现完全这个错误其实可以完全不用理会&#xff0c;因…