You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不阻塞主线程、不使用额外线程和循环的情况下等待变量变更

解决方案:基于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方法,确保信号不会遗漏。

注意事项

  1. 所有修改TemperatureLed的地方必须调用setTemperatureLed,不能直接赋值,否则信号无法发出,后续逻辑不会触发。
  2. 使用Qt::SingleShot连接或手动断开信号,避免多次触发OnTemperatureOverflow导致多个连接重复执行OnTemperatureLedOff。
  3. 如果DeviceCenter可能被提前销毁,需在析构函数中断开所有相关信号连接,避免悬空指针问题。

内容的提问来源于stack exchange,提问作者alberh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 04:53:11