我正在WPF中构建一个实时多线程应用程序,但是我在更新UI方面遇到了困难。
我有一个后台工作线程,其中包含确定要发送到市场的交易的逻辑。当有效交易发送到市场时,我通过主应用程序窗口中的事件接收这些交易的状态更新。我还有其他活动可以获得实时价格更新。
通过这些活动,我更新了UI。现在看来,我在整个应用程序中如此迅速地接收事件,UI无法跟上接收事件的速度 - 导致UI缓慢更新或根本不更新。基本上UI冻结了。在所有事件都被触发后,UI再次缓慢响应。一旦完全响应,UI就会显示我期待的数据。
我的问题是,如何在接收事件的同时实时更新UI?我一直在努力解决这个问题,所以任何帮助都会受到赞赏。
提前致谢!
答案 0 :(得分:11)
不要让工作线程通过事件将更新推送到UI线程,而是考虑让UI线程定期拉动(或轮询)它们。推送方法在很多情况下都很好,但有两个主要的缺点,对你不利。
我建议使用一个共享队列,其中工作线程将排队包含更新的数据结构,UI线程将出列并处理它。您可以让UI线程以策略性选择的间隔轮询队列,以便它永远不会陷入困境。队列将充当缓冲区而不是UI消息泵。随着更新数量的增加和流量的增加,它会缩小并增长。这是我正在谈论的简单图表。
[Worker-Thread] -> [Queue] -> [UI-Thread]
我首先从简单的队列方法开始,但是你可以把它带到创建一个管道的下一个逻辑步骤,其中有3个线程参与更新流程。工作线程将更新排队,UI线程像以前一样将它们出列。但是,可以在混合中添加一个新线程,以管理队列中等待的更新数量并使其保持在可管理的大小。如果队列仍然很小,它将通过转发所有更新来执行此操作,但是如果可以定义合理的合并操作,则将切换到安全模式并开始丢弃可以存在的更新,或者将多个更新合并为一个。以下是此模式可能如何工作的简单图表。
[Worker-Thread] -> [Queue-1] -> [Pipeline-Thread] -> [Queue-2] -> [UI-Thread]
再次,从简单的一个队列方法开始。如果需要更多控制,请转到管道模式。我已成功使用它们。
答案 1 :(得分:7)
您可能需要合并收到的事件,以免每次勾选都会导致GUI更新。如果您的GUI已经更新,请将它们批处理,并且只有在准备就绪时才让GUI处理下一批。如果Feed是高容量的(通常是活动交易数据更新的情况),您将无法创建将每个单独的tick作为其自包含刷新触发器的GUI。