首页 > 解决方案 > 如何使与 QTimer::timeout 关联的插槽可以被任何其他信号处理器(更高优先级)中断然后恢复?

问题描述

为了简化问题,假设我有一个QTimer,它将每 3000 毫秒触发一次超时事件。

QTimer timer;

QObject::connect(&timer, &QTimer::timeout, [&](){
    // do sth(rely on a public data structure)
}); 

timer.start(3000);

连接到timeout事件的 lambda 内部的操作依赖于公共数据结构。

并且应用程序持有一个QUdpSocket, 并将readyRead信号与一个槽函数连接起来。

QUdpSocket socket;
socket.bind(45454, QUdpSocket::ReuseAddressHint);

QObject::connect(&socket, &QUdpSocket::readyRead, [&](){
    //manipulate the public data structure
}

如您所见,连接到readyRead信号的 lambda 操作第一个 lambda 所依赖的公共数据结构。

所以我的问题是,我希望连接到readyRead信号的函数具有最高的“优先级”,也就是说,即使在 Qt 的事件循环中现在正在处理timeout插槽,它可以被中断并readyRead立即启动插槽,然后在它之后完成,恢复timeout插槽功能。有什么办法吗?

(我的作业是模拟 IEEE802.11 暴露/隐藏节点问题,它要求我必须在发送数据包之前/期间不断地监听通道。)

(显式调用QCoreApplication::processEvent会有帮助吗?)

标签: qtnetwork-programmingsimulationwifi

解决方案


我不熟悉 IEEE802.11 暴露/隐藏节点问题,但是我认为您不能像您所描述的那样“中断”您的代码。

处理此问题的一种可能方法是在不同线程上运行 readyRead 和超时槽的代码,然后使用某种同步机制(想到 QMutex)来访问公共数据(并获取其状态)。

IE

  1. 添加某种 uniqueid 来识别 public_data 当前状态

  2. timeout_slot 将获取锁,读取本地副本中的公共数据并释放锁,然后继续操作本地结构,最后在释放之前将再次获取锁并检查 uniqueid 是否已更改,如果是则提交您的工作,否则你必须重新开始。

  3. readyRead_slot 将获取锁,更新 uniqueid 然后继续工作


推荐阅读