QThread::wait: Thread tried to wait on itself

news2024/9/21 10:53:27

调用QThread的wait()方法时,报警:QThread::wait: Thread tried to wait on itself

原因:在自己的线程中调用线程的wait()方法。

解决方法:在线程外的其他线程中,调用线程的wait()方法。

示例代码如下:

MyObject.h

#ifndef MYOBJECT_H
#define MYOBJECT_H

#include <QObject>
#include <QThread>

class MyObject : public QObject
{
    Q_OBJECT
public:
    explicit MyObject(QObject *parent = nullptr);
    ~MyObject();
    
    void init();
    void quitThread();
    
    void test1();

public Q_SLOTS:
    void slotTest();
    
private:
    QThread *m_thread = nullptr;    
};

#endif // MYOBJECT_H

MyObject.cpp

#include "MyObject.h"
#include <qdebug.h>

MyObject::MyObject(QObject *parent) : QObject(parent)
{
    init();
}

MyObject::~MyObject()
{
    qDebug() << Q_FUNC_INFO << QThread::currentThreadId();
    
    quitThread();
}

void MyObject::init()
{
    m_thread = new QThread();
    connect(m_thread, &QThread::finished, m_thread, &QThread::deleteLater);
    connect(m_thread, &QThread::finished, this, [] {
        qDebug() << Q_FUNC_INFO << QThread::currentThreadId();
    });
    
    moveToThread(m_thread); // 将该对象移入线程中
    m_thread->start();
}

void MyObject::quitThread()
{
    qDebug() << Q_FUNC_INFO << QThread::currentThreadId();
    
    if (m_thread) {
        m_thread->quit();
        m_thread->wait();
    }
}

void MyObject::test1()
{
    qDebug() << Q_FUNC_INFO << QThread::currentThreadId();
}

void MyObject::slotTest()
{
    qDebug() << Q_FUNC_INFO << QThread::currentThreadId();
}

创建一个对话框,在对话框中测试:

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>
#include "MyObject.h"

class Dialog : public QDialog
{
    Q_OBJECT    
public:
    Dialog(QWidget *parent = nullptr);
    ~Dialog();
    
private:
    void init();
    
private:
    QPushButton *m_btnTest = nullptr;
    QPushButton *m_btnRelease = nullptr;
    MyObject *m_obj = nullptr;
    
};
#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include <qboxlayout.h>
#include <qthread.h>
#include <qdebug.h>

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    init();
}

Dialog::~Dialog()
{
}

void Dialog::init()
{
    setWindowTitle("线程测试");
    setFixedSize(360, 160);
    
    m_btnTest = new QPushButton("测试", this);
    m_btnTest->setFixedSize(100, 36);
    m_btnRelease = new QPushButton("释放对象", this);
    m_btnRelease->setFixedSize(100, 36);
    m_obj = new MyObject();     // 不需指定父对象
    
    qDebug() << Q_FUNC_INFO << QThread::currentThreadId();
    
    QHBoxLayout *lay = new QHBoxLayout(this);
    lay->addWidget(m_btnTest);
    lay->addWidget(m_btnRelease);
    
    connect(m_btnTest, &QPushButton::clicked, this, [this] {
        if (m_obj) {
            m_obj->test1();
            QMetaObject::invokeMethod(m_obj, "slotTest", Qt::QueuedConnection);
        }
    });
    
    connect(m_btnRelease, &QPushButton::clicked, this, [this] {
        if (m_obj) {
            m_obj->deleteLater();
            m_obj = nullptr;
        }
    });
}

运行界面如下:

点击【测试】按钮,打印信息如下所示:

void Dialog::init() 0x43f4
void MyObject::test1() 0x43f4
void MyObject::slotTest() 0x2790

由此可见,主线程的线程ID为0x43f4,子线程的线程ID为0x2790

点击【释放对象】按钮,打印信息如下所示:

virtual MyObject::~MyObject() 0x2790
void MyObject::quitThread() 0x2790
QThread::wait: Thread tried to wait on itself

由于使用的是MyObjec::deleteLater()函数,MyObjectt的析构函数是在子线程中执行的,子线程的退出也是在子线程中执行的,因而报警,且线程退出失败(没有执行QThread::finished)

代码修正:在释放MyObjec对象时,使用delete m_obj,代码如下:

    connect(m_btnRelease, &QPushButton::clicked, this, [this] {
        if (m_obj) {
            delete m_obj;
            m_obj = nullptr;
        }
    });

点击【测试】和【释放对象】按钮时,打印信息如下:

void Dialog::init() 0x1460
void MyObject::test1() 0x1460
void MyObject::slotTest() 0x644
virtual MyObject::~MyObject() 0x1460
void MyObject::quitThread() 0x1460
MyObject::init()::<lambda()> 0x644

由此可见,子线程的退出操作是在主线程中完成的,不仅没有报错,而且线程也成功退出了(执行了线程退出槽函数)

资源文件下载链接(免费):

https://download.csdn.net/download/ouyangxiaozi/89616335

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MATLAB学习之绘图篇(二维图)

目录 1.1基础图形绘制 1.1.1使用plot函数进行图形绘制 1.1.2为图像增加图例 1.1.3为图片增加标题以及坐标轴的描述 1.1.4控制坐标轴&#xff0c;边框以及网络 1.1.5在一个图像上绘制多条曲线 1.1.6在一个窗口绘制多个图像 1.1.7对图形的对象进行操作( 坐标属性&#xff…

LeetCode Hot100 二叉搜索树中第K小的元素

给定一个二叉搜索树的根节点 root &#xff0c;和一个整数 k &#xff0c;请你设计一个算法查找其中第 k 小的元素&#xff08;从 1 开始计数&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,1,4,null,2], k 1 输出&#xff1a;1示例 2&#xff1a; 输入&#xf…

【C/C++】C语言和C++实现Stack(栈)对比

我们初步了解了C&#xff0c;也用C语言实现过栈&#xff0c;就我们当前所更新过的有关C学习内容以栈为例子&#xff0c;来简单对比一下C语言和C。 1.C中栈的实现 栈的C语言实现在【数据结构】栈的概念、结构和实现详解-CSDN博客 &#xff0c;下面是C实现的栈&#xff0c; 在St…

ImageNet数据集和CIFAR-10数据集

一、为什么需要大量数据集 人工智能其实就是大数据的时代&#xff0c;无论是目标检测、图像分类、还是现在植入我们生活的推荐系统&#xff0c;“喂入”神经网络的数据越多&#xff0c;则识别效果越好、分类越准确。因此开源大型数据集的研究团队为人工智能的发展做了大量贡献…

QT教程-十五,Qt-5.14.2安卓开发环境配

目录 一&#xff0c;Qt需要的组件 二&#xff0c;需要的环境配置 1,JDK配置 1.1 配置JDK环境 1.2 Qt中配置JDK,SDK,NDK 2,创建Qt安卓项目 2.1 配置gradle-5.5.1-bin.zip文件 最近想开发一款安卓app应用&#xff0c;但是又不想去重新学习一个新的知识体系。于是在自己更为…

2024.8.5 作业

1> 使用有名管道实现&#xff0c;一个进程用于给另一个进程发消息&#xff0c;另一个进程收到消息后&#xff0c;展示到终端上&#xff0c;并且将消息保存到文件上一份 create.c #include <myhead.h> int main(int argc,const char *argv[]) {if(mkfifo("./lin…

在windows下生成的mac苹果电脑端可以执行的unity项目程序,在mac电脑不能执行的修改方法

在windows下开发Unity项目&#xff0c;如果要执行的电脑是mac&#xff0c;必须在windows下生成for mac的程序&#xff0c;发现拷贝到mac电脑后不能执行&#xff1a; 原因是改程序没有mac的执行权限: 修改方法&#xff1a; 先打开终端&#xff1a; 进入文件所在目录 cd Downlo…

✅【文献串读】Object Counting论文串读

get宝藏博主&#xff1a;Tags - 郑之杰的个人网站 (0809zheng.github.io) 目标计数(Object Counting) - 郑之杰的个人网站 (0809zheng.github.io) 目录 1.《CountGD: Multi-Modal Open-World Counting》 2.&#xff08;2024CVPR&#xff09;《DAVE – A Detect-and-Verif…

报表控件stimulsoft操作:使用 Stimulsoft 产品连接到 OData 源

Stimulsoft Ultimate &#xff08;原Stimulsoft Reports.Ultimate&#xff09;是用于创建报表和仪表板的通用工具集。该产品包括用于WinForms、ASP.NET、.NET Core、JavaScript、WPF、PHP、Java和其他环境的完整工具集。无需比较产品功能&#xff0c;Stimulsoft Ultimate包含了…

FFmpeg实战 - 解复用与解码

大纲目录 文章目录 前置知识音视频基础概念解复用、解码的流程分析FFMPEG有8个常用库 常见音视频格式的介绍aac格式介绍&#xff08;ADTS&#xff09;h264格式分析FLV和MP4格式介绍 FFmpeg解码解封装实战数据包和数据帧&#xff08;AVPacket/AVFrame&#xff09;AVPacket/AVFra…

VHDX 安装操作系统

前言 使用 Win11 作为主力系统&#xff0c;再通过 VHDX 虚拟硬盘来安装另外的 Windows 系统。使用 VHDX 安装系统的好处在于&#xff1a;不影响原系统&#xff0c;用完即删。 需求 安装双系统&#xff0c;使用 VHDX 安装 WinServer 2022。 操作步骤 创建 VHDX 打开磁盘管…

一道笔试题 - 无重复字符的最长子串

老生常谈的一道题&#xff0c;常见并 文章目录 描述预期结果Java代码 描述 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的最长子串的长度。 预期结果 Java代码 import java.util.HashSet; import java.util.Set;public class Demo2 {public static void main(S…

为什么回测效果非常好的策略实盘却不行?

这是一个絮絮叨叨的专题系列&#xff0c;跟大伙儿唠一唠量化相关的小问题&#xff0c;有感而发写到哪算哪&#xff0c;这是第二期&#xff0c;来唠个12块钱的~ 之前在某乎看到这个问题&#xff0c;说的是自己的MACD策略回测绩效不错&#xff0c;但实盘比较拉胯&#xff0c;希望…

pxe666666

1.下载图形化工具 2.init 5进入 3.配个ip 4.安装图形化生成kickstart自动安装脚本的工具 5.配置httpd 6.浏览器查看 7.设置 保存 8.检查有无问题 9.共享 10.测试 11编辑配置文件37及后的脚本&#xff0c;并注释掉 27 28 12.安装pxe 13.共享pxelinux.0数据文件的网络服务 14.查询…

函数实例讲解(四)

文章目录 提取不重复值&#xff08;INDEX、MATCH、COUNTIF&#xff09;1、INDEX2、MATCH3、COUNTIF 提取不重复的值的经典套路&#xff08;LARGE、SMALL、ROW&#xff09;1、ROW2、LARGE3、SMALL&#xff09; 制作Excel动态查询表四舍五入函数(ROUND、ROUNDUP、ROUNDDOWN&#…

shell 环境变量

shell 变量加载顺序 set设置了当前shell进程的本地变量&#xff0c;本地变量只在当前shell的进程内有效&#xff0c;不会被子进程继承和传递。 env仅为将要执行的子进程设置环境变量。 export将一个shell本地变量提升为当前shell进程的环境变量&#xff0c;从而被子进程自动继…

搭建pxe网络安装环境

实验目的&#xff1a; 搭建pxe网络安装环境实现服务器自动部署 实验原理&#xff1a; PXE 网络安装环境实现服务器自动部署的实验原理为&#xff1a; 待安装的服务器&#xff08;PXE 客户端&#xff09;开机时&#xff0c;BIOS 设置从网络启动&#xff0c;向网络发送请求。…

54 GRE-VPN 点到点

一 理论 1 GRE 概念 GRE&#xff08;Generic Routing Encapsulation&#xff0c;通用路由封装&#xff09;协议用来对某种协议&#xff08;如IP、以太网&#xff09;的数据报文进行封装&#xff0c;使这些被封装的数据报文能够在另一个网络&#xff08;如IP&#xff09;中传…

职场“老油条”的常规操作,会让你少走许多弯路,尤其这三点

有句话说得好&#xff1a;“在成长的路上&#xff0c;要么受教育&#xff0c;要么受教训。” 挨过打才知道疼&#xff0c;吃过亏才变聪明&#xff0c;从职场“老油条”身上能学到很多经验&#xff0c;不一定全对&#xff0c;但至少有可以借鉴的地方&#xff0c;至少能让你少走…

Python实现AI自动化微信回复脚本

脚本相关技术 wxauto Windows版本微信客户端&#xff08;非网页版&#xff09;自动化&#xff0c;可实现简单的发送、接收微信消息&#xff0c;简单微信机器人 GitHub地址 AI 脚本联动的是讯飞星火的api&#xff08;主要是免费且无限token数&#xff08;必须实名后才能领…