3

这个问题是我的问题的细化观察数据变化的不同方式

我的 C++ 应用程序中仍然有很多类,它们在复杂的数学例程和复杂的业务逻辑中经常更新(或可能更新)。

如果我采用“观察者”方法,并在每次更改实例值时发送通知,我将面临两大风险:

  • 发送通知本身可能会严重降低应用程序的速度
  • 如果用户界面元素需要通过更改进行更新,则它们会随着每次更改而更新,从而导致例如屏幕在某些业务逻辑正在执行时被更新数千次

有些问题可以通过添加缓冲机制来解决(当你要开始一个算法,当算法完成时,你会发送通知),但是由于业务逻辑可能在软件的很多地方执行,我们在菜单中选择了每个可能的操作之后,最终几乎在所有地方都添加了缓冲。

除了“观察者”方法,我还可以使用“标记-脏”方法,只标记已更改的实例,并在操作结束时告诉用户界面它应该自我更新。

同样,业务逻辑可以在应用程序中的任何地方执行,因此在实践中,我们可能必须在用户执行几乎每个操作之后添加一个额外的调用(告诉所有窗口它们应该自己更新)。

两种方法似乎都有相似但相反的缺点:

  • 使用“观察者”方法,我们有更新用户界面太多次的风险
  • 使用“mark-dirty”方法,我们有根本不更新用户界面的风险

这两个缺点都可以通过将每个应用程序操作嵌入到额外的逻辑中来解决(对于观察者:发送开始结束通知,对于标记脏:发送更新自己的通知)。

请注意,在非窗口应用程序中,这可能不是问题。例如,您可以使用 mark-dirty 方法,并且仅当某些计算需要数据时,它可能需要做一些额外的处理以防数据脏(这是一种缓存方法)。

但是,对于窗口应用程序,没有信号表明用户正在“查看您的屏幕”并且应该更新窗口。因此,您必须查看脏数据的真正好时机(尽管您可以对焦点事件做一些技巧)。

解决这个问题的好方法是什么?您是如何在应用程序中解决此类问题的?

请注意,我不想在我的应用程序的计算/数据模型部分引入窗口技术。如果需要窗口技术来解决这个问题,它只能用于我的应用程序的用户界面部分。

任何的想法?

4

3 回答 3

2

几年前我使用的一种方法是使用大型 Windows 应用程序,即使用WM_KICKIDLE. 所有可更新的东西都使用一个名为IdleTarget. 然后, AnIdleTargetManager拦截KICKIDLE消息并在已注册客户端列表上调用更新。在您的实例中,您可以创建要更新的特定目标列表,但我发现注册客户列表已经足够了。

我遇到的唯一问题是实时图表。由于图形的不断更新,仅使用 kick idle 消息会使 CPU 达到 100%。使用计时器休眠,直到下一次刷新解决了该问题。

如果您需要更多帮助 - 我可以以合理的价格提供......:-)

于 2010-09-08T12:31:28.677 回答
0

我正在考虑的另一点。

如果您对生成的事件数量以及它可能导致的额外工作感到不知所措,您可能有两个阶段的方法:

  • 做好工作
  • 犯罪

通知仅在提交时发送。

它确实有强制重写一些代码的缺点......

于 2010-09-08T13:36:55.400 回答
0

您可以将观察者模式与合并一起使用。不过,用 C++ 实现可能有点难看。它看起来像这样:

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

因此,即使您调用notify了 3 次,观察者实际上也不会收到通知,直到endCoalescing观察者只收到一次通知。

于 2010-09-08T14:06:06.160 回答