WPF 实时多线程股票交易应用程序

发布于 2024-09-24 08:43:00 字数 354 浏览 3 评论 0原文

我正在 WPF 中构建实时多线程应用程序,但在更新 UI 时遇到困难。

我有一个后台工作线程,其中包含确定将哪些交易发送到市场的逻辑。当有效交易发送到市场时,我会通过主应用程序窗口中的事件收到这些交易的状态更新。我还有其他活动可以接收实时价格更新。

通过这些事件,我更新了用户界面。现在看来,我在整个应用程序中接收事件的速度如此之快,以至于 UI 无法跟上接收事件的速度 - 导致 UI 更新缓慢或根本不更新。基本上 UI 冻结了。所有事件触发后,UI 会慢慢恢复响应。一旦完全响应,用户界面就会显示我期望的数据。

我的问题是,如何让 UI 在收到事件时实时更新?我已经为此苦苦挣扎了一段时间,所以任何帮助将不胜感激。

提前致谢!

I am building a real-time multi-threaded application in WPF, but i am having difficulties in updating the UI.

I have a background worker thread that contains logic which determines what trades to send into the market. When a valid trade is sent to the market, i receive status updates on these trades via events in my main application window. I have other events where i receive real-time price updates.

Through these events, i upate the UI. Now it appears that i receive events so rapidly through out the application, that the UI can't keep up with the speed at which events are received - causing the UI to update slowly or not at all. Essentially the UI freezes. After all events have fired, the UI slowly becomes responsive again. Once it is fully responsive, the UI shows the data that i am expecting.

My question is, how do i get the UI to update in real-time as fast as i receive events? I have been struggling with this for a while now, so any help would be appreciated.

Thanks in advance!

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

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

发布评论

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

评论(2

寄离 2024-10-01 08:43:00

不要让工作线程通过事件将更新推送到 UI 线程,请考虑让 UI 线程定期拉取(或轮询)它们。推送方法在很多情况下都很好,但有两个对您不利的主要缺点。

  • 在某个地方有一个昂贵的编组操作正在转移方法的执行以安全地执行 UI 更新(至少应该)。
  • 工作线程可以决定 UI 应更新的频率以及应执行的工作量。它很容易压垮消息泵。

我建议使用共享队列,其中工作线程会将包含更新的数据结构排入队列,而 UI 线程将出列并处理它。您可以让 UI 线程以策略性选择的时间间隔轮询队列,这样它就不会陷入困境。队列将充当缓冲区而不是 UI 消息泵。它会随着更新量的增减而缩小或增长。这是我正在谈论的内容的简单图表。

[Worker-Thread] -> [Queue] -> [UI-Thread]

我将首先从简单的队列方法开始,但您可以将其带到创建管道的下一个逻辑步骤,其中有 3 个线程参与更新流。像以前一样,工作线程将更新放入队列,UI 线程将它们出列。但是,可以添加一个新线程来管理队列中等待的更新数量并将其保持在可管理的大小。如果队列仍然很小,它将通过转发所有更新来实现这一点,但会切换到安全模式并开始丢弃您可以没有的更新,或者如果可以定义合理的合并操作,则将许多更新合并为一个。这是此模式如何工作的简单图表。

[Worker-Thread] -> [Queue-1] -> [Pipeline-Thread] -> [Queue-2] -> [UI-Thread]

再次,从简单的单队列方法开始。如果您需要更多控制,请转向管道模式。我已经成功地使用了两者。

Instead of having the worker thread push the updates to the UI thread via events consider having the UI thread pull (or poll) them periodically. The push method is fine in a lot of situations but has two major disadvantages that are working against you.

  • There is an expensive marshaling operation somewhere that is transferring execution of a method to perform the UI updates safely (at least there should be).
  • The worker thread gets to dictate how often the UI should update and by implication how much work it should perform. It can easily overwhelm the message pump.

I propose using a shared queue in which the worker thread will enqueue a data structure containing the update and the UI thread will dequeue and process it. You can have the UI thread poll the queue at a strategically chosen interval so that it never gets bogged down. The queue will act as the buffer instead of the UI message pump. It will shrink and grow as the amount of updates ebb and flow. Here is a simple diagram of what I am talking about.

[Worker-Thread] -> [Queue] -> [UI-Thread]

I would start with the simple queue approach first, but you could take this to the next logical step of creating a pipeline in which there are 3 threads participating in the flow of updates. The worker thread enqueues updates and the UI thread dequeues them like before. But, a new thread could be added to the mix that manages the number of updates waiting in the queue and keeps it at a manageable size. It will do this by forwarding on all updates if the queue remains small, but will switch into safe mode and start discarding the updates you can live without or combining many into one if a reasonable merge operation can be defined. Here is a simple diagram of how this pattern might work.

[Worker-Thread] -> [Queue-1] -> [Pipeline-Thread] -> [Queue-2] -> [UI-Thread]

Again, start with the simple one queue approach. If you need more control then move to the pipeline pattern. I have used both successfully.

凉墨 2024-10-01 08:43:00

您可能需要合并接收到的事件,这样并非每次更新都会导致 GUI 更新。如果您的 GUI 已经更新,则对它们进行批处理,并让 GUI 仅在准备就绪时才处理下一批。如果提要量很大(通常是活跃交易数据更新的情况),您将无法创建一个 GUI,将每个单独的价格变动反映为其独立的刷新触发器。

You probably need to coalesce received events such that not every tick results in a GUI update. Batch them up if your GUI is already updating, and have the GUI process the next batch only when it's ready. If the feed is high-volume (frequently the case with active trade data updates) you will not be able to create a GUI that reflects every individual tick as its own self-contained refresh trigger.

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