2010-09-08 131 views
2

这个问题是我的问题Different ways of observing data changes的改进。保持用户界面最新的最佳方式?

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

如果我去的“观察员”的方式,每一个实例的值发生改变时发出通知,我有2点大的风险:

  • 送出本身的应用减慢通知严重
  • 如果用户界面元素需要通过更改进行更新,它们会随着每次更改而更新,从而导致例如正在执行一些业务逻辑的屏幕正在执行时间

有些问题可以通过添加缓冲机制来解决(当您打算以算法开始时发送通知,以及当算法已完成),但由于业务逻辑可能会在软件中的许多地方执行,因此我们最终会在菜单中选择的每个可能操作后添加缓冲区。

除了'观察者'的问题,我还可以使用'mark-dirty'方法,只标记已被修改的实例,并在操作结束时告诉用户界面它应该自行更新。业务逻辑可以从应用程序中的任何地方执行,因此实际上在用户执行几乎每一个动作之后,我们可能不得不添加额外的呼叫(告诉所有窗口它们应该自己更新)。

两种方法似乎都差不多,但相反的缺点:

  • 随着“观察员”的方法,我们必须更新用户界面的风险太多次
  • 随着“标记脏”的方法,我们必须在所有

两个缺点可以通过额外的逻辑中嵌入每一个应用程序的行动(观察员来解决不更新用户界面的风险:发出启动结束的通知,对于标记脏:发送更新 - 你自己的通知)。

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

然而,对于窗口应用程序,也没有信号,用户在“看你的屏幕”和窗户应更新。所以没有真正的好时机,你必须查看脏数据(尽管你可以用焦点事件做一些技巧)。

解决此问题的最佳解决方案是什么?你是如何在你的应用程序中解决这样的问题的?

请注意,我不希望我的应用程序的计算/数据模型部分介绍了窗技术。如果需要开窗技术来解决这个问题,它只能用在我的应用程序的用户界面部分。

有什么想法?

+0

观察者是否可以设置一个事件或唤醒等待事件的线程的东西。这是这个线程,然后接管通知所有用户界面 – Chubsdad 2010-09-08 12:39:24

回答

2

我使用的一种方法是用几年前的大型Windows应用程序使用WM_KICKIDLE。所有可更新的东西都使用一个称为IdleTarget的抽象基类。然后IdleTargetManager拦截KICKIDLE消息并在注册客户列表上调用更新。在你的实例中,你可以创建一个特定的目标列表来更新,但我发现足够的注册客户端列表。

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

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

+0

好主意的工作。它有什么好处,它清楚地将业务逻辑部分(根本不知道任何用户界面)与用户界面部分分开。 – Patrick 2010-09-08 12:34:12

0

还有一点,我在想什么。

如果您是通过生成的事件的数量,并可能是导致额外的工作压得喘不过气来,你可能有两个阶段的办法:

  • 做的工作
  • 提交

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

它有强迫重写一些代码的缺点...

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当观察员只通知一次。