如何最好地保持用户界面更新?

3
这个问题是我之前提出的不同观察数据变化方式问题的细化。
我的C++应用程序中有很多类,这些类在复杂的数学例程和复杂的业务逻辑中经常被更新(或可能被更新)。
如果我采用“观察者”方法,并在每次实例值更改时发送通知,我有两个重大风险:
- 发送通知本身可能会严重减慢应用程序的速度 - 如果用户界面元素需要通过更改进行更新,则在执行某些业务逻辑时它们将被更新成千上万次,导致屏幕被更新成千上万次
一些问题可以通过添加缓冲机制来解决(在开始算法时发送通知,算法完成后再发送通知),但由于业务逻辑可能在软件中的许多位置上执行,因此我们几乎需要在每个菜单中选择每个可能的操作后添加缓冲。
与“观察者”方法不同,我还可以使用“标记-脏”方法,仅标记已更改的实例,在动作结束时告诉用户界面它应该更新自己。
同样,业务逻辑可以在应用程序的任何地方执行,因此在实践中,我们可能不得不在用户执行的几乎每个操作后添加一个额外的调用(告诉所有窗口它们应该更新自己)。
这两种方法似乎具有相似但相反的缺点:
- 通过“观察者”方法,我们有更新用户界面过多的风险。 - 通过“标记-脏”方法,我们有不更新用户界面的风险。
这两个缺点都可以通过将每个应用程序操作嵌入其他逻辑来解决(对于观察者:发送开始-结束通知,对于标记-脏:发送更新自己通知)。
请注意,在非窗口化应用程序中,这可能不是问题。例如,您可以使用标记 - 脏方法,只有在某些计算需要数据时,它可能需要处理一些额外的处理以防数据是脏的(这是一种缓存方法)。
然而,对于窗口应用程序而言,没有信号表明用户正在“查看您的屏幕”,也没有实际上好的时机让您查看脏数据(虽然您可以使用焦点事件进行一些技巧)。
有什么好的解决方案来解决这个问题?您如何在应用程序中解决这类问题?
请注意,我不想在我的应用程序的计算/数据模型部分引入窗口技术。如果需要使用窗口技术来解决此问题,则必须仅在我的应用程序的用户界面部分使用。
有任何想法吗?

观察者能否只设置一个事件或类似的东西,以唤醒等待该事件的线程。然后这个线程负责通知所有用户界面的工作。 - Chubsdad
3个回答

2
我曾经使用的一种方法是在几年前的一个大型Windows应用程序中使用WM_KICKIDLE。所有可更新的事物都利用一个抽象基类叫做IdleTarget。然后,一个IdleTargetManager拦截KICKIDLE消息,并在已注册客户端列表上调用更新。在您的情况下,您可以创建一个特定目标的更新列表,但我发现已注册客户端的列表足够了。
唯一需要注意的是实时图表。仅使用Kick Idle消息会导致CPU占用率达到100%,因为图表不断更新。使用计时器睡眠直到下一次刷新解决了这个问题。
如果您需要更多帮助-我提供合理的费率... :-)

好主意。它的优点在于它清晰地将业务逻辑部分(完全不知道任何用户界面)与用户界面部分分离开来。 - Patrick

0

你可以使用观察者模式与合并。不过在C++中实现可能会有些丑陋。它看起来会像这样:

m_observerList.beginCoalescing();
m_observerList.notify();
m_observerList.notify();
m_observerList.notify();
m_observerList.endCoalescing(); //observers are notified here, only once

所以即使您调用notify三次,观察者直到endCoalescing时才实际被通知,此时观察者只会被通知一次。


0

我还有一个想法。

如果您被生成的事件数量压垮了,并且可能导致额外的工作,您可以采取两个阶段的方法:

  • 完成工作
  • 提交

其中通知仅在提交时发送。

这确实有一个缺点,即迫使重写一些代码...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接