QT程序退出还占进程

问题情况

程序运行时的样子:
在这里插入图片描述
程序退出时的样子:
其跑到了后台进程里面:
程序退出了,但在任务管理器里查看,其从进程里面转移到后台进程了。
这种问题,怎么办,代码里,应该释放的也都释放了,为什么会出这个问题呢?
在后台的进程,还有时占些cpu,说明的确在运行,的确在做事情。
这首先怀疑到了是否线程的问题呢?

问题分析

1、线程析构了吗?

窗体的析构函数:

MainWindow::~MainWindow()
{
    if(nullptr != m_pCmdThread)
    {
        m_pCmdThread->deleteLater();
        delete m_pCmdThread;
    }

线程的析构函数:

CmdThread::~CmdThread()
{
    quit();
    wait();
}

看着都正常,问题出在那呢?
可能是quit(),wait()

quit()
告诉线程的事件循环以return 0(成功)退出。 相当于调用QThread :: exit(0)。如果线程没有事件循环,这个函数什么也不做。
wait()
阻塞线程,直到满足以下任一条件:
与此QThread对象关联的线程已经完成执行(即从run()返回)。 如果线程完成,该函数将返回true。 如果线程尚未启动,它也返回true。
时间毫秒已经过去了。 如果时间是ULONG_MAX(默认值),那么等待永远不会超时(线程必须从run()返回)。 如果等待超时,此函数将返回false。

这里非常关键的解释是quit(),quit(),不是线程退出,而是线程的事件循环退出,如果是继承的QThread,那么,自己实现了run方法,里面也没调用exec()方法,则这一个线程没有事件循环,这一点必须清楚。
没有事件循环,那么run方法的死循环就退不出来,我的代码是这样写的:

void CmdThread::run()
{
    qDebug("enter function CmdThread::run");
    m_pCmdService = new CmdService();
    QString strMessage;
    while(true)
    {
        switch (this->m_currentState)
        {
        case INIT_PORT:
        case OPEN_PORT:
            if(!m_pCmdService->openPort(*this->m_pBoardInfoDomain))
            {
                strMessage = QString::asprintf("串口%s连接失败", this->m_pBoardInfoDomain->serialName.c_str());
                emit sendMessage(1, strMessage);
                return;
            }

显然,是没有事件循环的,那这样,线程还是在一 直运行的,那么这种情况如何解决,方法很多,目的就是退出这一个while循环就可以了,其实也可以这样说,没有一个合适的方法退出正在运行的线程,如果强制退出,那样是危险的。
为了正式一些,就用官方推荐的方法如下:

void CmdThread::run()
{
    qDebug("enter function CmdThread::run");
    m_pCmdService = new CmdService();
    QString strMessage;
    while(true)
    {
     if(QThread::currentThread()->isInterruptionRequested())
        {
            break;
        }
        switch (this->m_currentState)
        {
        case INIT_PORT:
        case OPEN_PORT:
            if(!m_pCmdService->openPort(*this->m_pBoardInfoDomain))
            {
                strMessage = QString::asprintf("串口%s连接失败", this->m_pBoardInfoDomain->serialName.c_str());
                emit sendMessage(1, strMessage);
                return;
            }

触发的事件如下:

CmdThread::~CmdThread()
{
    requestInterruption();
    quit();
    wait();
}

就是在析构的时候停止线程。
这样,再测试发现,关闭窗体后,后台进程不会再存在了,这样就解决了这一个问题,这一个问题的关键点在于:
1、对quit,exit函数的理解,其是退出线程事件,不会退出线程的run方法
2、线程的退出,只能我自己写代码实现,没有其它的办法,在析构函数里退出就是一个很好的方法。
如果一个应该停止的任务在此线程上运行,则返回true。 requestInterruption()可以请求中断。
这个功能可以用来使长时间运行的任务干净地中断。 建议在耗时长的运行函数中定期执行此操作。 注意不要太频繁地调用,以保持较低的开销。
最后,以一张图来说明情况:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/10113.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【我的创作纪念日】恒川的创作一周年

机缘 大家好,我是热爱跑步的恒川,今天是个特殊的日子(我的创作纪念日),在去年的今天,我发了第一篇博文。去年的时候,刚接触到CSDN,只想把他当作一个学习的工具,后来&…

浅析时间复杂度与空间复杂度

时间复杂度 何为时间复杂度 算法的时间复杂度,是一个用于度量一个算法的运算时间的一个描述,本质是一个函数,根据这个函数能在不用具体的测试数据来测试的情况下,粗略地估计算法的执行效率,换句话讲时间复杂度表示的…

UNIX高级编程--管道

管道 管道是 UNIX 系统 IPC 的最高老形式,所有的 UNIX 系统都提供此种通信机制。管道有以下两种局限性。 历史上,它们是半双工(既数据只能在一个方向上流动)。现在,某些系统提供全双工管道,但是为了最佳的…

代码随想录算法训练营第五十七天 | 647. 回文子串、516. 最长回文子序列、动态规划总结

647. 回文子串 动规五部曲 1、确定dp数组(dp table)以及下标的含义 在判断字符串S是否为回文时,如果知道 s[1],s[2],s[3] 这个子串是回文的,那么只需要比较 s[0]和s[4]这两个元素是否相同,如果…

Motion Planning学习笔记一:配置空间、图、图搜索、图遍历

学习高飞博士的路径规划课程所总结的学习笔记。 目录 1、配置空间(Configuration Space, C-space) 2、图(Graphs) 3、图搜索(Graph Search Basis) 3.1、总体框架 3.2、两种基本的图遍历算法 3.3、启…

【Python】【进阶篇】十七、Python爬虫实现实时翻译

目录十七、Python爬虫实现实时翻译17.1 JS代码slat与sign17.2 Python代码表示参数17.3 完整程序实现十七、Python爬虫实现实时翻译 YD翻译是以异步方式实现数据加载的,要实现数据抓取,其过程极其繁琐。 上一节《Python爬虫的浏览器实现抓包》&#xff…

【hello Linux】Linux开发工具

目录 1. vim:文本编辑器 1.1 各种模式的切换 补充:ctrl r命令 1.2 命令模式的操作 1.3 插入模式的操作 1.4 底行模式的操作 1.5 配置vim环境 1.6 配置亲属关系 2. gcc/g:编译器 2.1 预处理: 2.2 编译: 2.3 汇编&#x…

如何利用ChatGPT辅助优化刷题性能

根据土著刷题共建群里的一个小伙伴反馈,刷题会出现切题卡顿的情况,有时会出现滑不动的情况。 定位问题 为了定位切题卡顿问题的具体原因,测试了高低端手机📱、切换2G、3G、4G低网络状态等各种影响切题的现实情况,经过借…

STM32F4_定时器精讲(TIM)

目录 1. 什么是定时器? 2. STM32定时器简介 2.1 高级控制定时器 TIM1和TIM8 2.1.1 TIM1和TIM8简介 2.1.2 时基单元 2.1.3 计数器模式 2.1.4 重复计数器 2.1.5 时钟选择 2.1.6 捕获/比较通道 2.1.7 输入捕获模式 2.1.8 其他功能 2.2 通用定时器 TIM2到TI…

Mysql 你还在一个字段一个索引吗

今天看到某系统的mysql在某时段存在thread_running线程数飙高触发告警,挤时间分析了该异常时间段的慢日志记录,并进行了sql优化 慢日志记录主要归为3个慢sql (编号1,2,3) 一、 1号sql原文 select * from feeds where topics_id &…

【MySQL数据库原理】MySQL Community安装与配置

目录 安装成功之后查看版本验证1、介绍、安装与配置数据库2、操作MySQL数据库3、MySQL数据库原理安装成功之后查看版本验证 SELECT VERSION();查看mysql版本号 1、介绍、安装与配置数据库 下载安装包:https://download.csdn.net/download/weixin_41194129/87672588 MySQL…

Visual studio C#中通过nuget安装sqlite库及C#中sliqte的用法

以前在Visual studio 的2017版中讲过如何使用sqlite,这里我们再次说说如何使用sqlite,以前Nuget使用还不是很流行很普及,大多数人不知道,但随着VS的升级,Nuget成为安装插件或者引用库文件标准的获取手段,所…

Qt Quick - TabBar

Qt Quick - TabBar使用总结一、概述二、调整选项卡三、Flickable标签三、定制化一、概述 TabBar其实就是选项卡,TabBar是由TabButton控件填充,TabBar可以与任何提供currentIndex属性的布局或容器控件一起使用,如StackLayout或SwipeView。Tab…

Vector - CAPL - CAN x 总线信息获取

在CAN&CANFD测试中,我们经常需要获取到CAN总线的负载、错误帧、过载帧、发送错误等等CAN总线上面的信息,这些信息如此重要,但是如果真的要写代码去实现也是相当不易的,那我们该如何去获取到的呢?下面我们就来一起看…

Object方法

私人博客 许小墨のBlog —— 菜鸡博客直通车 系列文章完整版,配图更多,CSDN博文图片需要手动上传,因此文章配图较少,看不懂的可以去菜鸡博客参考一下配图! 系列文章目录 前端系列文章——传送门 JavaScript系列文章—…

柔性数组【结构体和动态内存的结合】

全文目录前言柔性数组的定义语法柔性数组的特点柔性数组的使用柔性数组的优势前言 很多人可能没有听过柔性数组这个概念,但是在C99中柔性数组是确实存在的。我个人感觉有点像动态内存和结构体的结合。 柔性数组的定义语法 结构中的最后一个元素允许是未知大小的数…

NumPy 秘籍中文第二版:三、掌握常用函数

原文:NumPy Cookbook - Second Edition 协议:CC BY-NC-SA 4.0 译者:飞龙 在本章中,我们将介绍许多常用函数: sqrt(),log(),arange(),astype()和sum()ceil(),modf()&…

《Java8实战》第1章 Java 8、9、10 以及 11 的变化

如想了解 Oracle 公司对 JDK 的最新支持情况,请访问https://www.oracle.com/technetwork/java/java-se-supportroadmap.html。所有的示例代码均可见于图灵社区本书主页 http://ituring.com.cn/book/2659“随书下载”处。 1.1 为什么要关心 Java 的变化 Java8做的…

[MAUI 项目实战] 手势控制音乐播放器(三): 动画

文章目录吸附动画确定位置平移动画回弹动画使用自定义缓动函数多重动画点击动画项目地址上一章节我们创建了手势容器控件PanContainer,它对拖拽物进行包装并响应了平移手势和点击手势。拖拽物现在虽然可以响应手势操作,但视觉效果较生硬,一个…

总结一下Redis的缓存雪崩、缓存击穿、缓存穿透

缓存是提高系统性能的一种常见手段,其中Redis是一种常用的高性能缓存数据库。但是在使用缓存时,可能会遇到一些问题,比如缓存击穿、缓存穿透、缓存雪崩等问题,本文将介绍这些问题的概念、原因以及解决方案。 缓存击穿 缓存击穿指…