如何在不阻塞主线程、不使用额外线程和循环的情况下等待变量变更
解决方案:基于Qt信号槽的异步非阻塞改写
核心思路是用Qt的事件驱动+信号槽机制替代阻塞轮询,完全满足「不额外线程、不阻塞主线程、无循环」的要求。
步骤1:改造共享数据类,添加状态变更信号
首先要确保sharedData的TemperatureLed状态变更时能发出通知信号,以此替代轮询等待。修改SharedData类:
#include <QObject> #include <QReadWriteLock> class SharedData : public QObject { Q_OBJECT public: enum LedState { LedOn, LedOff }; Q_ENUM(LedState) // 原有成员 LedState TemperatureLed = LedOff; LedState SomeLed = LedOff; QReadWriteLock readWriteLock; // 必须通过此方法修改TemperatureLed,确保状态变更时发出信号 void setTemperatureLed(LedState newState) { QWriteLocker locker(&readWriteLock); if (TemperatureLed != newState) { TemperatureLed = newState; emit temperatureLedChanged(newState); } } signals: // 温度LED状态变更时触发的信号 void temperatureLedChanged(LedState state); };
步骤2:拆分原函数,用信号触发后续逻辑
把原OnTemperatureOverflow里的阻塞等待和后续操作拆分为前置处理、异步等待信号触发后置操作两个部分:
void DeviceCenter::OnTemperatureOverflow() { // 执行原有的前置处理逻辑 // some processes. QReadLocker readLocker(&sharedData.readWriteLock); if (sharedData.TemperatureLed == SharedData::LedOff) { // 如果当前已经是LedOff,直接执行后续逻辑 readLocker.unlock(); // 提前解锁,避免后续写锁冲突 OnTemperatureLedOff(); } else { // 监听TemperatureLed变为LedOff的信号,单次触发后自动断开 connect(&sharedData, &SharedData::temperatureLedChanged, this, [this](SharedData::LedState state) { if (state == SharedData::LedOff) { OnTemperatureLedOff(); // 手动断开连接,防止重复触发 disconnect(&sharedData, &SharedData::temperatureLedChanged, this, nullptr); } }, Qt::SingleShot); readLocker.unlock(); } } // 原函数中循环后的逻辑抽成单独的槽函数 void DeviceCenter::OnTemperatureLedOff() { QWriteLocker writeLocker(&sharedData.readWriteLock); sharedData.SomeLed = SharedData::LedOn; // 执行原有的后置处理逻辑 // some processes. }
关键说明
- 无阻塞无循环:彻底移除while轮询,用信号槽的异步通知替代,主线程可正常处理其他事件(比如设备的异步数据更新)。
- 无额外线程:所有逻辑都在Qt主线程的事件循环中执行,无需创建新线程。
- 线程安全:通过
QReadWriteLock保证共享数据的读写安全,且TemperatureLed的修改唯一入口是setTemperatureLed方法,确保信号不会遗漏。
注意事项
- 所有修改
TemperatureLed的地方必须调用setTemperatureLed,不能直接赋值,否则信号无法发出,后续逻辑不会触发。 - 使用
Qt::SingleShot连接或手动断开信号,避免多次触发OnTemperatureOverflow导致多个连接重复执行OnTemperatureLedOff。 - 如果
DeviceCenter可能被提前销毁,需在析构函数中断开所有相关信号连接,避免悬空指针问题。
内容的提问来源于stack exchange,提问作者alberh
相关产品推荐
相关产品推荐

