如何在高容量模型更新方案中处理无响应的UI

Ste*_*erg 5 c++ model-view-controller qt

我们使用的是Qt 4.8.2,我们有一个模型/视图设计(具体是QAbstractItemModel和QTreeview的子类).模型/树视图遵循视图驱动模型的典型原理 - 在用户展开相应的树视图节点之前,我们不会填充模型.

一旦节点被扩展并且数据可见,它就会受到工作(非UI)线程中发生的显示更新的影响.现在,当工作线程产生可能影响树视图的更改时,它会发出"更改"信号,该信号将映射到模型中的插槽.

问题是这些变化信号可以以很高的频率发出(例如,一秒钟内发生1500次事件),但有时它们可​​能适用于树视图当前显示的内容(因此可以忽略).当发生这种情况时,UI线程变得没有响应,因为(我假设)信号都排队,UI线程必须先处理它们才能恢复用户交互.

响应变化信号所需的时间非常短,但似乎UI线程仅在一小段延迟后"吃掉"信号 - 可能是为了避免过度更新导致屏幕闪烁或其他烦恼.

结果是UI保持冻结5或6秒,在此期间CPU活动非常低(可能是因为信号进入速度足够快,处理程序仍在等待操作中断); 一旦所有信号排队,线程最终消耗队列中的工作并在几毫秒内解决它.

我对此有几点想法:

  1. 是否有一些设置可以增加UI线程处理输入信号的攻击性?

  2. 在单独的线程中管理模型的更新是否可行?我的直觉是拒绝 - 看起来Qt机器太依赖于模型的独占所有权,并且在其访问周围放置适当的锁定保护将是复杂的并且违反了槽/信号范例的整个点.

  3. 我可以想出更复杂的方案来处理辅助线程中的这些信号; 例如,UI可以维护单独的多线程可见(非模型)数据结构,可以查询该数据结构以确定是否需要发送变化信号.类似地,我可以维护一个工作线程使用的单独队列,在那里我可以将事件批量更改为单个信号(例如,我可以提供不超过两次的信号).但是这些方法让我觉得有点像拜占庭式的问题,我认为这个问题在Qt UI编程领域绝对不是很常见.

m. *_* c. 3

我们有一个类似的应用程序,对基础数据进行了大量更新。问题归结为:
每秒 1500 次更新会导致 GUI 发生多少变化?
如果答案是变化少于 6 个,那么模型每秒应该只发出 6 个数据变化。如果是这种情况,当底层数据更改时,检查此更改是否会更改 GUI,仅在必要时从模型发出数据更改信号。
如果答案是每秒会有超过 6 次 gui 更改,那么我们得到的答案是没有人每秒可以看到超过 3 次更改。底层数据更改根本不应该更新 GUI。使用250毫秒的定时器,在定时器事件中,检查需要更新的小区,并更新它们。