【Qt】多线程
线程创建
自定义线程类
#ifndef CUSTOMETHREAD_H
#define CUSTOMETHREAD_H#include <QObject>
#include <QThread>
#include "add.h"class CustomeThread : public QThread
{Q_OBJECT
public:// Bind the thread kernel function.explicit CustomeThread(Add*& addPtr);private:// Run the thread kernel functionvirtual void run() override;
private:Add* m_addFuc {nullptr};
};#endif // CUSTOMETHREAD_H
主函数
#include <QCoreApplication>
#include <QDebug>
#include <QThread>
#include "add.h"
#include "customethread.h"int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);qDebug() << "Current thread id: " << QThread::currentThreadId();//Concrator the thread kernel function object.Add* ladd = new Add(); CustomeThread* thread = new CustomeThread(ladd);thread->start();return a.exec();
}
结果:
Current thread id: 0x36d0
current Thread: 0x7f50
100 + 200 = 300
计算的核心函数在子线程中进行。
通过创建一个线程的controller 类,绑定线程执行的kernel函数。然后再子线程的run函数里执行 kernel 函数。
改进
上面的程序中 kernel 函数和 执行线程并没有在同一个线程下,所以虽然Qt通过跨线程调用的机制,在子线程调用成功了,但是终究是一种不安全的方式,所以,为了保险起见,需要将 kernel函数再移入子线程。
#include <QCoreApplication>
#include <QDebug>
#include <QThread>
#include "add.h"
#include "customethread.h"int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);qDebug() << "Current thread id: " << QThread::currentThreadId();//Concrator the thread kernel function object.Add* ladd = new Add(); CustomeThread* thread = new CustomeThread(ladd);ladd->moveToThread(thread);thread->start();return a.exec();
}
线程循环
事件循环
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);return a.exec();
}
上面的 a.exec() 即让程序进入系统的事件循环,事件循环是一个特殊的死循环,其作用如下:
- 阻塞程序,使得线程一直执行。
- 在循环内部可以不断的监听系统发来的信号,并作出反应。
#include <QCoreApplication>
#include <QDebug>
#include <QThread>
#include <QTimer>
#include <QObject>#include "add.h"
#include "customethread.h"int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);qDebug() << "Current thread id: " << QThread::currentThreadId();Add* ladd = new Add();CustomeThread* thread = new CustomeThread(ladd);ladd->moveToThread(thread);thread->start();QTimer* timer = new QTimer();QObject::connect(timer, SIGNAL(timeout()), ladd, SLOT(add()));return a.exec();
}
在这个例子里面,使用了一个定时器,向子线程里的 kernel 对象发送信号,出发 add() 槽函数。但是最后并没有触发到。一个原因是: 此时的 ladd 已经在子线程了, 直接连接信号槽,大部分时候只能在信号和槽函数在同一个线程时生效。比如,我们不把 ladd移动到子线程中:
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);qDebug() << "Current thread id: " << QThread::currentThreadId();Add* ladd = new Add();CustomeThread* thread = new CustomeThread(ladd);// Not move ladd to subthread!!!!//ladd->moveToThread(thread);thread->start();QTimer* timer = new QTimer();QObject::connect(timer, SIGNAL(timeout()), ladd, SLOT(add()));return a.exec();
}
Main thread id: 0x5628
Current Thread: 0x5628
100 + 100 = 200
Current Thread: 0x5628
100 + 100 = 200
Current Thread: 0x5628
100 + 100 = 200
Current Thread: 0x5628
100 + 100 = 200
Current Thread: 0x5628
100 + 100 = 200
如何子线程的对象发信号?
可以这样连接信号和操
QObject::connect(timer, SIGNAL(timeout()), ladd, SLOT(add()), Qt::QueuedConnection);
向子线程发了信号,子线程就能接受吗?
但是发现即时这样也不能向子线程发信号,这是因为子线程中的run函数并没有调用事件循环,此时子线程已经结束退出了,所以可以在子线程的run函数中增加事件循环
void CustomeThread::run()
{exec();
}
Main thread id: 0x5384
Current Thread: 0x1638
100 + 100 = 200
Current Thread: 0x1638
自定义事件循环
相关文章:
【Qt】多线程
线程创建 自定义线程类 #ifndef CUSTOMETHREAD_H #define CUSTOMETHREAD_H#include <QObject> #include <QThread> #include "add.h"class CustomeThread : public QThread {Q_OBJECT public:// Bind the thread kernel function.explicit CustomeThre…...
腾讯云GPU服务器GN7实例NVIDIA T4 GPU卡
腾讯云GPU服务器GN7实例搭载1颗 NVIDIA T4 GPU,8核32G配置,系统盘为100G 高性能云硬盘,自带5M公网带宽,系统镜像可选Linux和Windows,地域可选广州/上海/北京/新加坡/南京/重庆/成都/首尔/中国香港/德国/东京/曼谷/硅谷…...
3. 爬取自己CSDN博客列表(自动方式)(分页查询)(网站反爬虫策略,需要在代码中添加合适的请求头User-Agent,否则response返回空)
文章目录 步骤打开谷歌浏览器输入网址按F12进入调试界面点击网络,清除历史消息按F5刷新页面找到接口(community/home-api/v1/get-business-list)接口解读 撰写代码获取博客列表先明确返回信息格式json字段解读 Apipost测试接口编写python代码…...
利用HTTP代理实现请求路由
嘿,大家好!作为一名专业的爬虫程序员,我知道构建一个高效的分布式爬虫系统是一个相当复杂的任务。在这个过程中,实现请求的路由是非常关键的。今天,我将和大家分享一些关于如何利用HTTP代理实现请求路由的实用技巧&…...
深度学习(36)—— 图神经网络GNN(1)
深度学习(36)—— 图神经网络GNN(1) 这个系列的所有代码我都会放在git上,欢迎造访 文章目录 深度学习(36)—— 图神经网络GNN(1)1. 基础知识2.使用场景3. 图卷积神经网…...
深入理解JVM——垃圾回收与内存分配机制详细讲解
所谓垃圾回收,也就是要回收已经“死了”的对象。 那我们如何判断哪些对象“存活”,哪些已经“死去”呢? 一、判断对象已死 1、引用计数算法 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器就加一&…...
基于SSH框架实现的管理系统(包含java源码+数据库)
资料下载链接 介绍 基于SSH框架的管理系统 简洁版 ; 实现 登录 、 注册 、 增 、 删 、 改 、 查 ; 可继续完善增加前端、校验、其他功能等; 可作为 SSH(Structs Spring Hibernate)项目 开发练习基础模型…...
图像识别代做服务:实现创新应用的新契机
导言: 随着人工智能和图像处理技术的不断进步,图像识别已经成为了许多领域中的关键应用。然而,图像识别技术的开发和应用往往需要庞大的团队和大量的资源。这就是为什么图像识别代做服务正在崭露头角。本文将探讨图像识别代做服务如何成为实现…...
Coreutils工具包,Windows下使用Linux命令
之前总结过两篇有关【如何在Windows系统下使用Linux的常用命令】的文章: GnuWin32,Windows下使用Linux命令 UnxUtils工具包,Windows下使用Linux命令 今天再推荐一个类似的工具包Coreutils 一、简介 GNU core utilities是GNU操作系统基本…...
神经网络基础-神经网络补充概念-13-python中的广播
概念 在 Python 中,广播(Broadcasting)是一种用于在不同形状的数组之间执行二元操作的机制。广播允许你在不显式复制数据的情况下,对不同形状的数组进行运算。这在处理数组的时候非常有用,尤其是在科学计算、数据分析…...
HDFS原理剖析
一、概述 HDFS是Hadoop的分布式文件系统(Hadoop Distributed File System),实现大规模数据可靠的分布式读写。HDFS针对的使用场景是数据读写具有“一次写,多次读”的特征,而数据“写”操作是顺序写,也就是…...
css学习2(利用id与class修改元素)
1、id选择器可以为标有特定id的html元素指定特定的样式。 2、选择器以#开头,后跟某id的属性值。 3、class选择器用于描述一组元素的样式,class可以在多个元素使用。 4、类选择器用.选择。 5、指定特定的元素使用class。 6、元素的多个类用空格分开&…...
wsl2(debian)安装python的不同版本例如3.8
要在Debian上安装 Python 3.8,可以按照以下步骤操作: 1.确保你的 Debian 系统已经更新到最新版本,可以使用以下命令更新: sudo apt update sudo apt upgrade2.安装 Python 3.8 的依赖项,以及构建 Python 时需要的工具…...
Python教程(9)——Python变量类型列表list的用法介绍
列表操作 创建列表访问列表更改列表元素增加列表元素修改列表元素删除列表元素 删除列表 在Python中,列表(list)是一种有序、可变的数据结构,用于存储多个元素。列表可以包含不同类型的元素,包括整数、浮点数、字符串等…...
springboot+VUE智慧公寓管理系统java web酒店民宿房屋住宿报修信息jsp源代码
本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 springbootVUE智慧公寓管理系统 系统有2权限…...
神经网络基础-神经网络补充概念-36-dropout正则化
概念 Dropout 是一种常用的正则化技术,用于减少深度神经网络中的过拟合问题。它在训练过程中随机地将一部分神经元的输出置为零,从而强制模型在训练过程中学习多个独立的子模型,从而减少神经元之间的依赖关系,提高模型的泛化能力…...
Go语言基础之变量和常量
标识符与关键字 标识符 在编程语言中标识符就是程序员定义的具有特殊意义的词,比如变量名、常量名、函数名等等。 Go语言中标识符由字母数字和_(下划线)组成,并且只能以字母和_开头。 举几个例子:abc, _, _123, a123 关键字 关…...
Spring Boot 项目实现 Spring AOP
【注】实现在SpringBoot项目中,同时给两个类的方法添加AOP前置通知 1、创建一个SpringBoot项目 2、创建两个目标类和方法 package com.tqazy.learn_spring_project.spring_aop;import org.springframework.stereotype.Service;/*** ClassName SpringAopUserServi…...
Baumer工业相机堡盟工业相机如何通过BGAPISDK设置相机的固定帧率(C#)
Baumer工业相机堡盟工业相机如何通过BGAPI SDK设置相机的固定帧率(C#) Baumer工业相机Baumer工业相机的固定帧率功能的技术背景CameraExplorer如何查看相机固定帧率功能在BGAPI SDK里通过函数设置相机固定帧率 Baumer工业相机通过BGAPI SDK设置相机固定帧…...
js拼接字符串
在js中,你可以使用字符串拼接的方式创建新的字符串。 下面是一些常用的方法: 1、使用运算符: var str1 "Hello"; var str2 "World"; var result str1 " " str2; console.log(result); // 输出…...
突破B站字幕处理瓶颈:BiliBiliCCSubtitle全流程解决方案
突破B站字幕处理瓶颈:BiliBiliCCSubtitle全流程解决方案 【免费下载链接】BiliBiliCCSubtitle 一个用于下载B站(哔哩哔哩)CC字幕及转换的工具; 项目地址: https://gitcode.com/gh_mirrors/bi/BiliBiliCCSubtitle 一、问题发现:字幕处理的现实困境…...
如何高效管理LiteDB数据库?LiteDB.Studio实战指南与深度解析
如何高效管理LiteDB数据库?LiteDB.Studio实战指南与深度解析 【免费下载链接】LiteDB.Studio A GUI tool for viewing and editing documents for LiteDB v5 项目地址: https://gitcode.com/gh_mirrors/li/LiteDB.Studio 在现代软件开发中,嵌入式…...
palworld-host-save-fix全攻略:解决幻兽帕鲁存档迁移难题的实战指南
palworld-host-save-fix全攻略:解决幻兽帕鲁存档迁移难题的实战指南 【免费下载链接】palworld-host-save-fix 项目地址: https://gitcode.com/gh_mirrors/pa/palworld-host-save-fix 在幻兽帕鲁的冒险旅程中,更换服务器或迁移平台时的存档丢失问…...
遥感小白别慌!ENVI 5.6 基础操作保姆级教程:从打开文件到剖面图显示,一篇搞定
遥感新手实战指南:ENVI 5.6 从零到剖面分析的完整工作流 第一次打开ENVI时,那个布满英文按钮的界面和密密麻麻的菜单栏,是不是让你瞬间想起了大学时被专业课支配的恐惧?别担心,三年前的我也是这样——面对一幅Landsat…...
英雄联盟智能助手:如何在选人阶段获得不公平优势?终极指南揭秘本地化工具LeagueAkari
英雄联盟智能助手:如何在选人阶段获得不公平优势?终极指南揭秘本地化工具LeagueAkari 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League…...
Pixel Couplet Gen入门必看:Streamlit Components封装像素春联React组件
Pixel Couplet Gen入门必看:Streamlit Components封装像素春联React组件 1. 项目介绍 Pixel Couplet Gen是一款基于ModelScope大模型驱动的创意春联生成器。与传统春联设计不同,它采用了独特的8-bit像素游戏风格,将中国传统春节元素与复古电…...
Python安全开发之简易Xss检测工具(详细注释)
核心代码:import requests # requests 库 - HTTP 请求处理库 # 【常用功能】: # requests.get(url) - 发送 HTTP GET 请求 # requests.post(url, data) - 发送 HTTP POST 请求 # response.text - 获取响应体内容(字符串) #…...
Self Service Password与LDAP集成实战:从部署到问题排查
1. Self Service Password与LDAP集成概述 自助密码重置功能已经成为企业IT基础设施中不可或缺的一部分。想象一下,当员工在深夜加班时忘记密码,又找不到IT支持人员,这种场景下的自助解决方案就显得尤为重要。Self Service Password࿰…...
VISA 标准深度剖析:寄存器基控制规范与函数接口研究
VISA 标准深度剖析:寄存器基控制规范与函数接口研究 VISA(Virtual Instrument Software Architecture)是仪器控制领域的标准 API,它为不同总线(GPIB、USB、LAN、PXI 等)提供了统一的编程接口。本文将 VISA 函数按功能分为 8 大类,并逐一解析其作用、核心函数及使用场景…...
Nunchaku FLUX.1-dev GPU算力优化:TensorRT加速推理实测对比
Nunchaku FLUX.1-dev GPU算力优化:TensorRT加速推理实测对比 如果你正在使用Nunchaku FLUX.1-dev模型生成图片,可能会发现一个问题:生成速度不够快,特别是当你想批量出图或者尝试不同参数时,等待时间有点长。 今天我…...
