基本信息
SDK: QT5.9
编程语言: C++
应用场景: 并发, 低延时,低资源场景下的 数据处理方案
基本流程: 数据计算->数据更新->数据发送
功能特点:
①可通过UI配置 多个数据计算单元 并发或者 顺序执行,
②执行QT程序的工控机硬件资源有限, 数据的更新和数据的发送确保必要的时候执行
③精准计时实现固定频率从串口发送数据到下位机处理
方案描述:
计算单元
单个计算单元的计算量并不大, 线程处理不适用, 采用定时器+事件循环的方式实现类似C++20协程的概念来实现
计算单元通过 定时器m_fadeTimer连接updateDmxValues()函数, 计时器周期性触发计算数据的函数
m_fadeTimer = new QTimer(this);
connect(m_fadeTimer, &QTimer::timeout, this, &Cue::updateDmxValues);
更新单元
更新单元通过定时器来精准计时,周期性更新由多个计算单元处理后得出的有效数据, 将更新的数据保存到新的变量中, 作为一帧数据为数据的发送做准备,
// 设置定时器,每秒触发50次(20ms间隔)
updateTimer.setInterval(20);
connect(&updateTimer, &QTimer::timeout, this, &impl_seq::sendDmxUpdate);
发送单元
当数据更新后, 开启发送定时器, 周期性的发送由 数据更新单元保存的当前需要发送的数据帧, 并确保当有数据更新的时候, 数据发送保持开启, 没有数据更新的时候, 数据发送功能关闭, 节约资源.
m_sendTimer = new QTimer(this);
bool connected = connect(m_sendTimer, &QTimer::timeout, this, &Impl_comm::sendSeqPacket);
qDebug() << “Signal connected:” << connected;
关键点解析
多个数据计算单元可能并发执行, 在数据计算期间, 数据更新定时器要cover整个计算过程, 数据计算频次为50次/秒,等价于一个计算单元20ms计算一次数值(数值随时间渐变), 为确保数据准确(最终发送出去的数据和计算数据一致(不丢数据, 不错数据) , 数据更新函数也要保证至少每20ms触发一次, 数据发送单元同理, 即数据计算单元计算数据, 数据更新单元捕获最新数据, 数据发送单元稳定发送数据流, 保证数据流输出低延迟的前提下, 尽量减小资源的占用.
点击添加图片描述(最多60个字)
编辑
具体实现
计算单元部分示例及说明
void Cue::startInDelay()
{
}
void Cue::startFade()
{
//原子整数类型变量updateTimerFlag, 确保多个计算单元对标志位的操作不会丢失(每有一个计算单元执行,该标志位累加1)
//只有当updateTimerFlag为0的时候才会触发更新计时器,即当前计算单元是第一个执行的.
}
//计算单元计算数据
void Cue::updateDmxValues()
{
// QElapsedTimer类型的成员m_elapsedTimer, 区别于qtimer, 精准计算时间,处理数据
//数值随时间渐变, 输出具体的计算值
{
{
//时间结束, 停止计算单元的定时器
{
//原子整数类型标志位减1
//只有当updateTimerFlag标志位值为0的时候(即没有计算单元在执行),updateTimer停止.
}
void Cue::startOutDelay()
{
}
总结说明
多个计算单元的并发执行, 计算量较小, 通过定时器+事件循环实现, 更新定时器 和 发送计时器 需要在 还有计算单元执行的周期内, 保持运行状态, 触发 数据更新和数据发送 函数, 所以这里采用原子整数类型累加标志位updateTimerFlag和sendTimerFlag(示例中未展示) 来管理定时器的打开和关闭, 确保更新和发送的正常工作的同时, 当标志位为0时,停止无效的数据更新以及数据流的发送. 节省资源, 优化性能.