保持用户界面最新的最佳方法是什么?

发布于 2024-09-18 09:27:28 字数 1098 浏览 6 评论 0原文

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

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

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

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

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

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

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

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

  • 使用“观察者”方法,我们存在多次更新用户界面的风险
  • 使用“标记脏”方法,我们存在不更新用户界面的风险 这两个缺点都

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

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

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

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

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

有什么想法吗?

This question is a refinement of my question Different ways of observing data changes.

I still have a lot of classes in my C++ application, which are updated (or could be updated) frequently in complex mathematical routines and in complex pieces of business logic.

If I go for the 'observer' approach, and send out notifications every time a value of an instance is changed, I have 2 big risks:

  • sending out the notifications itself may slow down the applications seriously
  • if user interface elements need to be updated by the change, they are updated with every change, resulting in e.g. screens being updated thousends of times while some piece of business logic is executing

Some problems may be solved by adding buffering-mechanisms (where you send out notifications when you are going to start with an algorith, and when the algorithm is finished), but since the business logic may be executed on many places in the software, we end up adding buffering almost everywhere, after every possible action chosen in the menu.

Instead of the 'observer' aproach, I could also use the 'mark-dirty' approach, only marking the instances that have been altered, and at the end of the action telling the user interface that it should update itself.

Again, business logic may be executed from everywhere within the application, so in practice we may have to add an extra call (telling all windows they should update themselves) after almost every action executed by the user.

Both approaches seem to have similar, but opposite disadvantages:

  • With the 'observer' approach we have the risk of updating the user-interface too many times
  • With the 'mark-dirty' approach we have the risk of not updating the user-interface at all

Both disadvantages could be solved by embedding every application action within additional logic (for observers: sending out start-end notifications, for mark-dirty: sending out update-yourself notifications).

Notice that in non-windowing applications this is probably not a problem. You could e.g. use the mark-dirty approach and only if some calculation needs the data, it may need to do some extra processing in case the data is dirty (this is a kind of caching approach).

However, for windowing applications, there is no signal that the user is 'looking at your screen' and that the windows should be updated. So there is no real good moment where you have to look at the dirty-data (although you could do some tricks with focus-events).

What is a good solution to solve this problem? And how have you solved problems like this in your application?

Notice that I don't want to introduce windowing techniques in the calculation/datamodel part of my application. If windowing techniques are needed to solve this problem, it must only be used in the user-interface part of my application.

Any idea?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

流殇 2024-09-25 09:27:28

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

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

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

An approach I used was with a large windows app a few years back was to use WM_KICKIDLE. All things that are update-able utilise a abstract base class called IdleTarget. An IdleTargetManager then intercepts the KICKIDLE messages and calls the update on a list of registered clients. In your instance you could create a list of specific targets to update but I found the list of registered clients enough.

The only gotcha I hit was with a realtime graph. Using just the kick idle message it would spike the CPU to 100% due to constant updating of the graph. Use a timer to sleep until the next refresh solved that problem.

If you need more assistance - I am available at reasonable rates...:-)

独行侠 2024-09-25 09:27:28

我在思考的另一点。

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

  • 完成工作
  • 提交

,仅在提交时发送通知。

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

Another point I was thinking about.

If you are overwhelmed by the number of events generated, and possibly the extra-work it is causing, you may have a two phases approach:

  • Do the work
  • Commit

where notifications are only sent on commit.

It does have the disadvantage of forcing to rewrite some code...

许仙没带伞 2024-09-25 09:27:28

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

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

因此,即使您调用 notify 三次,观察者在 endCoalescing 之前实际上不会收到通知,而观察者只收到一次通知。

You could use the observer pattern with coalescing. It might be a little ugly to implement in C++, though. It would look something like this:

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

So even though you call notify three times, the observers aren't actually notified until endCoalescing when the observers are only notified once.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文