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

13

我正在使用WPF构建一个实时多线程应用程序,但在更新UI方面遇到了困难。

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

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

我的问题是,我如何使UI与我接收事件的速度一样快地实时更新?我已经苦苦挣扎了一段时间,所以任何帮助将不胜感激。

提前感谢!

2个回答

11

不要让工作线程通过事件将更新推送到UI线程,请考虑使UI线程定期轮询以获取(或拉取)它们。在许多情况下,推送方法都很好用,但存在两个主要缺点正在对你起作用。

  • 某处存在一个昂贵的封送操作,该操作将执行UI更新的方法转移至安全地执行(至少应该这样)。
  • 工作线程决定了UI更新的频率,从而暗示了它应该执行多少工作量。它可以轻松地淹没消息泵。

我建议使用共享队列,在其中,工作线程将排队包含更新和UI线程将出列并处理它的数据结构。您可以使UI线程以战略选择的时间间隔轮询队列,以便它永远不会陷入困境。队列将充当缓冲区,而不是UI消息泵。随着更新的涨落,队列将收缩和增长。这是我所说内容的简单图示。

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

我会从简单的队列方法开始,但你可以将其带到下一个合乎逻辑的步骤,创建一个管道,在其中有3个线程参与更新流程。工作线程将更新入队,UI线程像以前一样出队。但是,可以添加一个新线程来管理队列中等待的更新数量并将其保持在可管理的大小。它将通过转发所有更新来完成此操作,如果队列保持较小,则会切换到安全模式并开始丢弃您可以不需要的更新或将许多更新合并为一个,如果可以定义合理的合并操作。这是该模式可能工作方式的简单图示。

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

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


太棒了,谢谢Brian。这就是我要找的答案。简而言之,不要让引发的事件直接更新UI,而是将它们排队,使用定时器定期从队列中弹出这些更新并更新UI。这样,UI就在您的控制下更新,定时器间隔可以根据我的需求进行调整。 - c0D3l0g1c
没错!让UI决定何时准备好更新,而不是将责任交给工作线程。 - Brian Gideon
你能提供一个示例代码来说明你所说的吗? - KeyvanSFX

7

如果您的GUI已经在更新,请尝试合并接收到的事件,以便不是每个tick都导致GUI更新。 如果正在更新,则将它们批处理,并且仅当GUI准备好处理下一批时,才进行下一批处理。 如果数据源的频率很高(通常是活动交易数据更新的情况),则无法创建反映每个单独tick作为自包含刷新触发器的GUI。


在单位时间内,人们通常只能对UI线程进行有限次数的单独调用,否则它将不再响应。定期以一定间隔批量更新诸如UI列表之类的元素也可以极大地帮助^^ - Oskar Duveborn

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