QTimer::singleShot导致定时器资源耗尽解决方法

打印 上一主题 下一主题

主题 1047|帖子 1047|积分 3141

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
参考文章:Qt QTimer::singleShot题目及用法
  1. 题目形貌

QTimer::singleShot定时器事件超时,如果此时类内对象已经被回收,定时器事件调用已经释放的类内资源时会引起瓦解。
这通常是由于定时器的回调函数(槽函数)在执行时可能会导致事件循环被阻塞,进而导致定时器无法正常触发,或者在高频率调用时,定时器的数目敏捷增加,造成资源消耗过大。
  1. QTimer::singleShot(100, this, [=]() {
  2.         LOG(INFO) << QString::fromLocal8Bit("____QTimer::singleShot testtest____").toStdString();
  3.         LOG(INFO) << QString::number(i).toStdString();
  4. });
复制代码
2. 百分百复现

可利用以下代码:
在while语句中不绝利用QTimer::singleShot。
  1. while (1)
  2. {
  3.         QTimer::singleShot(100, this, [=]() {
  4.                 LOG(INFO) << QString::fromLocal8Bit("____QTimer::singleShot testtest____").toStdString();
  5.                 LOG(INFO) << QString::number(i).toStdString();
  6.         });
  7. }
复制代码
 
报错如图所示:

3. 解决方法1:利用QCoreApplication::processEvents()

  1. while (1)
  2. {
  3.         QCoreApplication::processEvents();
  4.         QTimer::singleShot(100, this, [=]() {
  5.                 LOG(INFO) << QString::fromLocal8Bit("____QTimer::singleShot testtest____").toStdString();
  6.                 LOG(INFO) << QString::number(i).toStdString();
  7.         });
  8. }
复制代码
   QCoreApplication::processEvents() 是 Qt 框架中的一个函数,用于处置惩罚事件循环中的待处置惩罚事件。它的主要作用是使应用程序可以或许在某些环境下处置惩罚事件,比如用户输入、定时器超时等,而不会阻塞程序的执行。
    QCoreApplication::processEvents() 的作用
  

  • 处置惩罚事件:当调用 processEvents() 时,Qt 会处置惩罚全部待处置惩罚的事件,包括定时器事件。这意味着即使在某个长时间运行的操作中,定时器也有机会被触发,从而制止了定时器的回调函数无法执行的题目。
  • 制止阻塞:如果在槽函数中执行了耗时的操作,调用 processEvents() 可以让事件循环继续运行,处置惩罚其他事件,防止应用程序由于一个长时间运行的操作而完全无相应。
  • 释放资源:通过让事件循环处置惩罚其他事件,processEvents() 可以资助释放一些资源,制止由于定时器未能及时触发而造成的资源泄漏。
  4. 解决方法2:用定时器代替QTimer::singleShot

  1. while (1)
  2. {
  3.         QTimer *t = new QTimer;
  4.         connect(t, &QTimer::timeout, [=]() {
  5.                 LOG(INFO) << QString::fromLocal8Bit("____QTimer::singleShot testtest____").toStdString();
  6.                 LOG(INFO) << QString::number(i).toStdString();
  7.         });
  8.         t->setSingleShot(true);
  9.         t->start(50);
  10. }
复制代码

  1. while (1)
  2. {
  3.         QTimer *t = new QTimer;
  4.         connect(t, &QTimer::timeout, [=]() {
  5.                 t->stop();
  6.                 t->deleteLater();
  7.                 LOG(INFO) << QString::fromLocal8Bit("____QTimer::singleShot testtest____").toStdString();
  8.                 LOG(INFO) << QString::number(i).toStdString();
  9.         });
  10.         t->start(50);
  11. }
复制代码
5. 解决方法3:设置interval为0

  1. while (1)
  2. {
  3.         QTimer *t = new QTimer;
  4.         t->singleShot(0, this,connect(t, &QTimer::timeout, [=]() {
  5.                 LOG(INFO) << QString::fromLocal8Bit("____QTimer::singleShot testtest____").toStdString();
  6.                 LOG(INFO) << QString::number(i).toStdString();
  7.         });
  8. }
复制代码

  1. while (1)
  2. {
  3.         QTimer::singleShot(0, this,connect(t, &QTimer::timeout, [=]() {
  4.                 LOG(INFO) << QString::fromLocal8Bit("____QTimer::singleShot testtest____").toStdString();
  5.                 LOG(INFO) << QString::number(i).toStdString();
  6.         });
  7. }
复制代码
固然这个方法可以使其不报错,但是由于设置interval为0,对于时间间隔为0的事件,乃至连QSingleShotTimer都不需要创建,而是直接用invokeMethod去调用相应的slot,所以定时器不算相应了。
   参考文章:QTimer源码分析(以Windows下实现为例)_qtimer::singleshot源码及分析-CSDN博客
  

 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

杀鸡焉用牛刀

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表