马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
参考文章:Qt QTimer::singleShot题目及用法
1. 题目形貌
QTimer::singleShot定时器事件超时,如果此时类内对象已经被回收,定时器事件调用已经释放的类内资源时会引起瓦解。
这通常是由于定时器的回调函数(槽函数)在执行时可能会导致事件循环被阻塞,进而导致定时器无法正常触发,或者在高频率调用时,定时器的数目敏捷增加,造成资源消耗过大。
- QTimer::singleShot(100, this, [=]() {
- LOG(INFO) << QString::fromLocal8Bit("____QTimer::singleShot testtest____").toStdString();
- LOG(INFO) << QString::number(i).toStdString();
- });
复制代码 2. 百分百复现
可利用以下代码:
在while语句中不绝利用QTimer::singleShot。
- while (1)
- {
- QTimer::singleShot(100, this, [=]() {
- LOG(INFO) << QString::fromLocal8Bit("____QTimer::singleShot testtest____").toStdString();
- LOG(INFO) << QString::number(i).toStdString();
- });
- }
复制代码
报错如图所示:
3. 解决方法1:利用QCoreApplication::processEvents()
- while (1)
- {
- QCoreApplication::processEvents();
- QTimer::singleShot(100, this, [=]() {
- LOG(INFO) << QString::fromLocal8Bit("____QTimer::singleShot testtest____").toStdString();
- LOG(INFO) << QString::number(i).toStdString();
- });
- }
复制代码 QCoreApplication::processEvents() 是 Qt 框架中的一个函数,用于处置惩罚事件循环中的待处置惩罚事件。它的主要作用是使应用程序可以或许在某些环境下处置惩罚事件,比如用户输入、定时器超时等,而不会阻塞程序的执行。
QCoreApplication::processEvents() 的作用
- 处置惩罚事件:当调用 processEvents() 时,Qt 会处置惩罚全部待处置惩罚的事件,包括定时器事件。这意味着即使在某个长时间运行的操作中,定时器也有机会被触发,从而制止了定时器的回调函数无法执行的题目。
- 制止阻塞:如果在槽函数中执行了耗时的操作,调用 processEvents() 可以让事件循环继续运行,处置惩罚其他事件,防止应用程序由于一个长时间运行的操作而完全无相应。
- 释放资源:通过让事件循环处置惩罚其他事件,processEvents() 可以资助释放一些资源,制止由于定时器未能及时触发而造成的资源泄漏。
4. 解决方法2:用定时器代替QTimer::singleShot
- while (1)
- {
- QTimer *t = new QTimer;
- connect(t, &QTimer::timeout, [=]() {
- LOG(INFO) << QString::fromLocal8Bit("____QTimer::singleShot testtest____").toStdString();
- LOG(INFO) << QString::number(i).toStdString();
- });
- t->setSingleShot(true);
- t->start(50);
- }
复制代码 或
- while (1)
- {
- QTimer *t = new QTimer;
- connect(t, &QTimer::timeout, [=]() {
- t->stop();
- t->deleteLater();
- LOG(INFO) << QString::fromLocal8Bit("____QTimer::singleShot testtest____").toStdString();
- LOG(INFO) << QString::number(i).toStdString();
- });
- t->start(50);
- }
复制代码 5. 解决方法3:设置interval为0
- while (1)
- {
- QTimer *t = new QTimer;
- t->singleShot(0, this,connect(t, &QTimer::timeout, [=]() {
- LOG(INFO) << QString::fromLocal8Bit("____QTimer::singleShot testtest____").toStdString();
- LOG(INFO) << QString::number(i).toStdString();
- });
- }
复制代码 或
- while (1)
- {
- QTimer::singleShot(0, this,connect(t, &QTimer::timeout, [=]() {
- LOG(INFO) << QString::fromLocal8Bit("____QTimer::singleShot testtest____").toStdString();
- LOG(INFO) << QString::number(i).toStdString();
- });
- }
复制代码 固然这个方法可以使其不报错,但是由于设置interval为0,对于时间间隔为0的事件,乃至连QSingleShotTimer都不需要创建,而是直接用invokeMethod去调用相应的slot,所以定时器不算相应了。
参考文章:QTimer源码分析(以Windows下实现为例)_qtimer::singleshot源码及分析-CSDN博客
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |