Qt释放线程资源的一些工程上的方法.md

2023-05-16

Qt官方文档的方法
QThread创建在栈上,然后QObject需要配合QThread释放资源
直接上代码。结束的时候线程quit and wait

直接上代码

class Controller : public QObject
{
    Q_OBJECT
    QThread workerThread;
public:
    Controller() {
        Worker *worker = new Worker;
        worker->moveToThread(&workerThread);
        connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);

    ~Controller() {
        workerThread.quit();
        workerThread.wait();
    }

上了关键核心代码。
直接按照顺序来说。

1.观察析构函数
    ~Controller() {
        workerThread.quit();
        workerThread.wait();
    }

一步步来

工作线程quit跟wait退出结束,发出finished信号。
2. 线程退出
        connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
1
线程退出通知QObject对象删除

3. QThread释放
由于QThread在栈上,所以会自己销毁。

这三部完美的释放了线程资源。

我的做法
我上面讲的第二种方法实际上一开始写的并不好,虽说你把我的代码QObject跟QThraed加上析构函数输出发现也会释放,但是还是会有一些小问题。感谢知乎大佬指出来了。我直接上正确的结论。

工程代码在这里
https://github.com/CryFeiFei/Qt_Teach/tree/master/Qt_Teach/Thread2

我的QThread是放到堆上的。即下面的KThread

直接上我的代码。

    m_workerThread = new KThread();
    WorkThread* worker = new WorkThread();
    worker->moveToThread(m_workerThread);

    //等工作的QObject结束,让线程停止结束
    connect(worker, &WorkThread::workFinished, m_workerThread, [this]()
    {
        m_workerThread->quit();
        m_workerThread->wait();
    });

    //线程停止发给QObject让他自己销毁。
    connect(m_workerThread, &QThread::finished, worker, &WorkThread::deleteLater);

    // QObject销毁之后,让线程自己销毁。
    connect(worker, &WorkThread::destroyed, m_workerThread, &QThread::deleteLater);

解释都在备注上。

对比Qt官方的文档,也就是把QThread申请放到了堆上,然后多了一步释放QThread的操作。

    // QObject销毁之后,让线程自己销毁。
    connect(worker, &WorkThread::destroyed, m_workerThread, &QThread::deleteLater);

有兴趣可以自己下载代码调试下,会发现KThread跟worker的析构函数都完美释放了。

释放线程资源必须要做的(避免死锁
一定要等线程停止之后,再销毁线程

QWaitCondition
一定要等线程停止之后,再销毁线程

生产者消费者是用QWaitCondition来进行同步的。

现在我想手动把这个流程停掉

大概有这么几种情况。

比如生产者生产过快,还在wait,这时候我们的线程需要马上停止。

生产者线程在这里wait

if (listBuffer.size() == bufferSize)
{
    bufferNotFull.wait(&mutex);
}

这时候是没有办法把生产者停掉的,如果强行delete,那就未知了,运气好,不崩溃,运气差,就crash了。

再看看我们的控制代码是在上面这段代码之前的。

while(1)
{
    //xxxxxxx
    if (m_bPause)
    {
        emit workPause();
        continue;
    }
    //..................
    //xxxxx
    if (listBuffer.size() == bufferSize)
    {
        bufferNotFull.wait(&mutex);
    }
    
    //xxxxxxx
}


也就是这里死锁之后,我们的生产者是永远停不了的。

同理,消费者过快也会出现这个问题。

所以需要我们在释放这种资源的时候要手动调用下两个条件变量的

xxxx.wakeAll();
xxxx.wakeAll();

这样能够避免线程释放资源发生死锁。导致crash。

还有一个方法。
QWaitCondition 的wait是有一个超时时间的,你可以设定一个超时时间,这样就会进入下一次循环,也会避免死锁了。逃)
 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt释放线程资源的一些工程上的方法.md 的相关文章

  • Qt中线程同步的几种方法详解

    1 QMutex类 QMutex类就像一把锁 xff0c 在互斥量以前上锁 xff08 QMutex lock xff09 xff0c 而后在使用完互斥量以后解锁 xff08 QMutex unlock xff09 好比下面的代码 xff1
  • Qt中多线程同步总结示例

    1 QMutex QMutex mutex void func mutex lock mutex unlock 2 QMutex联手QMutexLocker 在复杂函数或者异常处理中 xff0c 对mutex进行lock 和unlock 操
  • vnc远程连接ubuntu,如何实现vnc远程连接ubuntu教程图解

    Ubuntu Linux是由南非人马克 沙特尔沃思 Mark Shuttleworth 创办的基于Debian Linux的操作系统 Ubuntu几乎包含了所有常用的应用软件 xff1a 文字处理 电子邮件 软件开发工具和Web服务等 用户
  • 什么是元学习?

    作者 Aleksandr Movchan 编译 VK 来源 Medium 人工智能的一个基本问题是它无法像人类一样高效地学习 许多深度学习分类器显示了超人的表现 xff0c 但需要数百万个训练样本 知识不共享 xff0c 并且每个任务都独立
  • Qt-多线程-QThread分析总结

    QThread是Qt提供的线程类 xff0c 每一个QThread均可管理一个线程 其具有两种使用方式 xff1a 1 继承为QThread的子类 xff1b 2 继承为QObject的子类 xff0c 并使用QObject moveToT
  • C++中 二重指针详解

    前言 上篇博文讲到数组和指针的一些关系 xff0c 本篇博文会在这基础之上讲解一些更为复杂的指针 xff0c 这些指针在笔试题中经常出现 xff0c 对刚毕业找工作的大学生有很大的作用 指向指针的指针 在指针篇 xff08 1 xff09
  • C++中数组初始化方法

    定义 xff1a int pia 61 new int 10 array of 10 uninitialized ints 此 new 表达式分配了一个含有 10 个 int 型元素的数组 xff0c 并返回指向该数组第一个元素的指针 xf
  • 类对象的内存和堆空间的内存及初始化详解

    对象的内存 对象的内存可以存在于 3 种地方 xff1a 全局区 xff08 数据段 xff09 xff1a 全局变量栈空间 xff1a 函数里面的局部变量堆空间 xff1a 动态申请内存 xff08 malloc new等 xff09 文
  • C++内存空间管理

    1 C 43 43 内存机制 1 栈 Stack xff0c 函数中的局部变量 xff0c 由编译器负责分配释放 xff0c 函数结束 xff0c 变量释放 2 堆 Heap xff0c 通过new 申请的内存 xff0c 由delete或
  • Qt中跨线程下信号和槽的使用方法

    connect用于连接qt的信号和槽 xff0c 在qt编程过程中不可或缺 它其实有第五个参数 xff0c 只是一般使用默认值 xff0c 在满足某些特殊需求的时候可能需要手动设置 Qt AutoConnection xff1a 默认值 x
  • Qt 中开启线程的多种方式小结

    简介1 继承 QThread 重写 run 函数2 继承 QObject 调用 moveToThread3 继承 QRunnable 重新 run 函数 xff0c 结合 QThreadPool 实现线程池4 使用 C 43 43 11 中
  • Qt中exec函数的作用

    Qt中的exec 方法到处可见 xff0c 例如 xff1a QCoreApplicaton exec QApplication exec QDialog exec QThread exec QMenu exec 那么 xff0c 这些ex
  • 在Qt中使用全局变量的两种方式,及出现无法解析的命令的问题

    很多小伙伴在Qt编程时 xff0c 不会使用全局变量 xff0c 其实基本有两种方式来定义使用全局变量 xff0c 第一种是根据c c 43 43 的extern来进行多文件的使用 xff0c 第二种方法就是把全局变量放在类中 xff0c
  • Qt中信号槽形参值传递,引用传递,指针传递的实例及总结

    在同一个线程中 当信号和槽都在同一个线程中时 xff0c 值传递参数和引用传递参数有区别 xff1a 值传递会复制对象 xff1b xff08 测试时 xff0c 打印传递前后的地址不同 xff09 引用传递不会复制对象 xff1b xff
  • vnc远程连接,5个步骤教你如何轻松实现vnc远程连接

    当我们在进行vnc远程连接时 xff0c 往往找不到有用的工具来支撑我们的工作 那当我们在进行vnc远程连接时 xff0c 有什么工具能让我们快速实现vnc远程连接呢 xff1f iis7服务器管理工具 如图 xff1a IIS7服务器管理
  • 关于qt信号槽传指针与释放指针

    今天 xff0c 意外发现qt中信号槽传指针的方式进行时 xff0c 会发生释放不掉指针所分配的空间的情况 定义一个信号 void emit showTime Data 槽 void slot showTime Data 在发出信号之前动态
  • Qt-信号和槽函数传递自定义参数前需注册自定义数据类型

    Qt 信号和槽函数参数只能是基于 Qt 的基础类型的 xff0c 比如 QString int bool 等 xff0c 如果想传递自定义类型默认情况下是行不通的 要想在 Qt 的信号和槽函数之间传递自定义类型 xff0c 可以先将自己的自
  • Qt 设置窗口背景图片的几种方法实例

    1 在paintEvent事件中绘制图片 void Widget paintEvent QPaintEvent ev QPainter painter this painter drawPixmap rect QPixmap 34 bg j
  • Qt事件处理的几种方式

    Qt提供了5种事件处理和事件过滤的方法 xff1a 1 重写事件处理器函数 这是大部分情况最常用的一种 xff0c 如重写 paintEvent mousePressEvent keyPressEvent 等事件处理器虚函数 2 重写 QO

随机推荐