在WPF窗口中,我有一个绘制实时数据的折线图(WPF的Quinn-Curtis实时图表)。简而言之,对于每个新值,我调用SetCurrentValue(x,y)方法,然后使用UpdateDraw()方法来更新图表。
数据通过另一个线程中的TCP连接进入。每个新值都会导致DataReceived事件,其处理程序应将值绘制到图表中,然后更新它。从逻辑上讲,我无法直接调用UpdateDraw(),因为我的图表位于UI线程中,该线程与数据所在的线程不同。
所以我调用 Dispatcher.Invoke(new Action(UpdateDraw())) - 这样就可以了,只要我更新max。 30次/秒。更频繁地更新时,Dispatcher无法跟上并且图表更新的速度比数据的速度慢。我使用模拟数据的单线程情况对此进行了测试,没有Dispatcher就没有问题。
所以,我的结论是 Dispatcher对于这种情况来说太慢了。我实际上需要更新100-200次/秒!
有没有办法在Dispatcher上安装turbo,还是有其他方法可以解决这个问题?欢迎任何建议。
答案 0 :(得分:10)
一个选项是使用共享队列来传递数据。
在数据出现的地方,您将数据推送到队列的末尾:
lock (sharedQueue)
{
sharedQueue.Enqueue(data);
}
在UI线程上,您可以找到一种方法来读取此数据,例如:使用计时器:
var incomingData = new List<DataObject>();
lock (sharedQueue)
{
while (sharedQueue.Count > 0)
incomingData.Add(sharedQueue.Dequeue());
}
// Use the data in the incomingData list to plot.
这里的想法是你没有传达数据的进来。因为你有一个恒定的数据流,我怀疑这不是问题。我并不是说上面给出的确切实现是其余部分,但这是关于一般性的想法。
我不确定您应该如何检查新数据,因为我对应用程序的详细信息没有足够的了解;但这可能是你的开始。
答案 1 :(得分:6)
你需要的是疯子 - 你真的不需要每秒100-200次更新,特别是因为屏幕通常以每秒60次更新运行。无论如何,人们都不会看到它们。
每秒30次更新就足够了 - 人们不会看到差异。我在T&amp; S的高负荷情况下对一些财务数据进行了性能问题,直到我做到了 - 现在图表看起来更好。
让Dispatcher尽可能少地移动。
答案 2 :(得分:4)
我仍然想知道为什么当你的显示器甚至无法快速显示时,你想要每秒更新一次图表200次。 (请记住,普通平板显示器的更新速率为60 fps)
如果每秒只能更新60次,每秒更新200次有什么用? 您也可以批量传入数据并以60 fps更新图表,因为无论如何您都无法看到差异。
如果它不仅仅是显示数据,而是你正在做其他事情 - 比如说你正在监视它以查看它是否达到某个阈值 - 而不是我建议将系统拆分为2部件:一部分全速监控,另一部分以显示器可以处理的最大速度独立显示:60 fps。
所以请告诉我们为什么你要更频繁地更新ui-control,而不是向用户显示。
答案 3 :(得分:0)
WPF绘图发生在一个单独的线程中。根据你的图表复杂程度,你的PC必须有一个兆下降的视频卡,以跟上每秒100帧。 WPF使用Direct3D在屏幕上绘制所有内容,并在Vista中添加了优化视频驱动程序(在Windows 7中进行了改进)。所以,在XP上,你可能会因为设计不佳的操作系统上的高数据输出率而遇到麻烦。
尽管如此,我认为没有理由以每秒超过30-60帧的速度将信息打印到屏幕上。 来吧!即使是FPS射手也不需要玩家那么强烈的反应。你想告诉我你的糟糕图表吗? :)如果通过这个输出,你产生一些副作用,这是你真正需要的,那么它是完全不同的故事。那么请告诉我们更多关于这个问题的信息。