【背景】一个类似Windows任务管理器的性能界面。该界面有多个曲线图同时定时刷新,每个曲线图包括多条曲线更新,数据更新频率大概为一秒一次。程序中曲线图已封装为自定义的图表类,给出数据更新接口。
【初始方案】主程序设计方案上,采用数据收集和数据更新分开的方式,即数据收集线程仅收集并解析来自数据源的数据,并分门别类的存储到共享结构体中。数据更新线程在收到数据更新信号之后,把新的数据刷新到图表中。
【存在问题】数据刷新时,鼠标拖拽主界面移动时存在停顿,且停顿频率与数据刷新频率相当。尤其是当数据量较大或更新频率加快时,停顿效果更新严重。
【问题分析】经调试发现,虽然数据收集线程在对数据收集后已完成数据的解析工作,并将整理好的数据推送给更新线程。但在曲线图更新的过程中,曲线图实例需要从已有曲线的数据拉取出来,删除存在时间最早的数据,再将新的数据更新到已有数据中。这一过程对于单个曲线图同时存在多条曲线的更新时耗时较长,尤其对于主界面同时存在多个曲线图的情况时,更甚。由此导致数据在刷新过程中存在较大程度的延时情况,从主界面的使用情况看,即鼠标拖拽时,出现停顿甚至是程序未响应的发生。
【解决方法】数据收集线程在整理完数据后,将数据通过图表实例的更新接口给入,该接口从对已有的数据进行更新,并保存在实例成员中,但不做刷新处理。在数据收集线程做完本次数据收集和整理过程之后,通过信号量通知更新线程。更新线程获得信号后,调用图表实例的刷新接口,刷新接口将已准备好的数据直接更新到界面中,不再处理其数据,如此一来,在动态更新曲线的过程中,鼠标拖拽不再出现停顿或程序停止运行的情况。
上述过程,可从Demo代码中下载,通过配置其中的 USING_QTIMER 或 USING_STD_THREAD 调用不同的处理方案(注意,demo使用了Qt的QChart,使用QtCreater需安装相应的模块,Demo中的数据处理过程以延迟模拟)