Qt 定时器放在线程中执行,支持随时开始和停止定时器。

📅 2026/7/23 18:11:00
Qt 定时器放在线程中执行,支持随时开始和停止定时器。
前言因为项目需要定时检查网络中设备是否能连通需要定时去做ping操作若是网络不通则ping花费时间比较久局域网大概4秒钟才能结束当然如果设置超时时间啥的也能很快返回就是会报QProcess提前关闭的警告。此外我想要在设备连接后才去开始定时ping要是断开后则停止定时器停止ping。网上有很多定时器使用线程的例子但是没有讲到可以随时停止和开始的那种本文结合实例使用线程去执行定时器的定时操作。一、定义定时器和线程变量。在头文件中定义#include QTimer #include QThread #include QString #include QProcess /** 监听网线拔出或者wifi断开情况的定时器 ***/ QTimer *detectNetCablePulloutTimer NULL; /** 执行定时器的线程 **/ QThread *detectNetCablePulloutTimerThread NULL; /** 开始检测网线拔出时或者wifi断开时的定时器 **/ void startDetectNetCablePulloutTimer(); /** 停止定时器 **/ void stopDetectNetCablePulloutTimer(); private slots: /** 检测网络连接情况的槽函数在线程中执行 **/ void checkDeviceIsOnline();二、开始定时器、停止定时器以及销毁定时器代码。开始定时器代码void CurrentXXXClass::startDetectNetCablePulloutTimer() { // 先停止确保开始之前是停止状态 stopDetectNetCablePulloutTimer(); if (detectNetCablePulloutTimer NULL) { // 注意构造函数是带this参数的这个必须这么写否则定时器槽函数无法在子线程中执行 detectNetCablePulloutTimerThread new QThread(this); // 注意构造函数是不带this参数的这个必须这么写否则定时器槽函数无法在子线程中执行 detectNetCablePulloutTimer new QTimer(); // 5秒执行一次局域网断开时一般耗时4-5秒 detectNetCablePulloutTimer-setInterval(5000); // 定时操作放在线程中执行 detectNetCablePulloutTimer-moveToThread(detectNetCablePulloutTimerThread); // 定时任务放在线程中执行, 必须指定参数-Qt::DirectConnection connect(detectNetCablePulloutTimer, QTimer::timeout, this, CurrentXXXClass::checkDeviceIsOnline, Qt::DirectConnection); void (QTimer::*pStartFun)() QTimer::start; // 线程开始时调用定时器的开始 connect(detectNetCablePulloutTimerThread, QThread::started, detectNetCablePulloutTimer, pStartFun); // 线程结束时调用定时器的结束所以要停止定时器只要调用线程的quit方法 // 同时防止提示定时器停止和开始不在同一线程错误 connect(detectNetCablePulloutTimerThread, QThread::finished, detectNetCablePulloutTimer, QTimer::stop); } detectNetCablePulloutTimerThread-start(); }停止定时器代码void CurrentXXXClass::stopDetectNetCablePulloutTimer() { if (detectNetCablePulloutTimerThread ! NULL) { // 会调用定时器的stop方法 detectNetCablePulloutTimerThread-quit(); } }销毁定时器在析构函数中执行//销毁指针变量-注意先后顺序 if (detectNetCablePulloutTimerThread ! NULL) { detectNetCablePulloutTimerThread-quit(); detectNetCablePulloutTimerThread-wait(); delete detectNetCablePulloutTimerThread; detectNetCablePulloutTimerThread nullptr; } if (detectNetCablePulloutTimer ! NULL) { // 定时器在线程中创建(父类不是当前类)让对象自己在所属线程销毁 detectNetCablePulloutTimer-deleteLater(); }三、在槽函数中执行耗时操作。此槽函数是在子线程中执行若是执行完后要回到主线程执行某操作则必须通过发送一个信号方式才能达到效果。void CurrentXXXClass::checkDeviceIsOnline() { QString ip 192.168.1.1; // 若是timer使用了线程则此函数在子线程中执行执行比较耗时的操作 QProcess pingProcess; // 不设置-w参数 QString strArg ping ip -n 1 -i 2; // qt 6 开始命令的方法 pingProcess.startCommand(strArg, QIODevice::ReadOnly); // 不带等待时间参数 pingProcess.waitForReadyRead(); // 不带等待时间参数 pingProcess.waitForFinished(); QString p_stdout QString::fromLocal8Bit(pingProcess.readAllStandardOutput()); bool bPingSuccess false; // 通过特殊字符串进行判断ping是否成功 if (p_stdout.contains(TTL)) { // 网络连通 bPingSuccess true; } else { // 网络不通 bPingSuccess false; } }