QThread::sleep在系统时间修改后失效问题求助
问题分析与解决方案
这问题我之前踩过坑!核心原因是QThread::sleep()依赖系统的实时时钟(wall-clock time),当你把系统时间往回调整时,它的等待逻辑直接就崩了。
为什么会卡住?
举个例子:假设你在系统时间T时刻调用了sleep(1),这个函数的逻辑是等待系统时间走到T+1秒才会返回。但你执行timedatectl把系统时间改成了远早于T的2015-11-23,那系统时间要走到T+1秒需要好几年的时间,你的线程自然就一直卡在sleep里,再也不会输出日志了。
解决办法
我们需要用不依赖系统实时时钟的方式来实现定时等待,Qt里有两种常用方案:
方案1:用QElapsedTimer实现基于真实流逝时间的等待
这种方式适合单纯的循环定时场景,完全不受系统时间修改的影响:
void TestThread::run() { QElapsedTimer timer; while (1) { qDebug() << "sleep"; timer.start(); // 循环等待直到真实流逝了1秒 while (timer.elapsed() < 1000) { QThread::msleep(10); // 每次睡10ms,避免占用过多CPU } } }
QElapsedTimer底层用的是单调时钟(monotonic clock),这个时钟只会持续向前走,不管系统时间怎么被修改、甚至回拨,它都能准确计算真实流逝的时间。
方案2:用QTimer+事件循环(适合需要处理信号的线程)
如果你的线程还需要处理其他Qt信号,这种方式更合适,而且Qt 5.4及以上版本的QTimer默认会用单调时钟:
void TestThread::run() { QTimer timer; // 绑定定时触发的逻辑 connect(&timer, &QTimer::timeout, [](){ qDebug() << "sleep"; }); timer.setInterval(1000); // 1秒触发一次 timer.start(); exec(); // 启动线程的事件循环,让QTimer能正常工作 }
这种方式下,即使修改系统时间,QTimer的触发间隔依然是真实的1秒,不会出现卡住的情况。
内容的提问来源于stack exchange,提问作者Nong Van Hieu
相关产品推荐
相关产品推荐

