【问题标题】:WPF dispatcher performance (100-200 updates/sec)WPF 调度程序性能(100-200 更新/秒)
【发布时间】:2010-11-08 13:29:08
【问题描述】:

在 WPF 窗口中,我有一个绘制 实时数据 的折线图(用于 WPF 的 Quinn-Curtis 实时图表)。简而言之,对于每个新值,我调用一个 SetCurrentValue(x, y) 方法,然后调用 UpdateDraw() 方法来更新图表。

数据通过另一个线程中的 TCP 连接传入。每个传入的新值都会引发一个 DataReceived 事件,其处理程序应将该值绘制到图表上,然后对其进行更新。从逻辑上讲,我不能直接调用 UpdateDraw(),因为我的图表在 UI 线程中,这与数据进入的线程不同。

所以我调用 Dispatcher.Invoke(new Action (UpdateDraw()) ) - 只要我更新最大值,它就可以正常工作。 30次/秒。更频繁地更新时,Dispatcher 跟不上,图表更新速度比数据输入慢。我使用模拟数据的单线程情况对此进行了测试,没有 Dispatcher 没有问题。

所以,我的结论是 Dispatcher 对于这种情况来说太慢了。我实际上需要更新 100-200 次/秒!

有没有办法在 Dispatcher 上添加涡轮增压器,或者有其他方法可以解决这个问题吗?欢迎任何建议。

【问题讨论】:

  • 您真的需要图表每秒更新 100/200 次吗?或者您只是每秒获得 100/200 个数据包?
  • 感谢您的建议,但我们确实需要 100 次更新/秒。请参阅下面我对您的帖子的评论。
  • 您使用的是哪种显示器。绝大多数显示器仅以 60Hz 更新,因此尝试以更快的速度推送更新毫无意义。一旦传入数据速率超过监视器帧速率,最好的办法是批量传入数据并每帧更新一次 UI。
  • -1 没有告诉我们你为什么要每秒更新图表 100 次以上。出于此线程中所述的许多原因,这样做绝对不是一个好主意。
  • @Pieter:不,我认为我们不应该将自己局限于技术解决方案。如果有人试图做一些不明显的事情并且不想接受显而易见的解决方案,那么深入挖掘,找出真正的问题是正确的。

标签: c# wpf multithreading


【解决方案1】:

一种选择是使用共享队列来传递数据。

数据来的地方,你把数据推到队列的末尾:

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.

这里的想法是你没有传达数据正在进入。因为你有一个恒定的数据流,我怀疑这不是问题。我并不是说上面给出的确切实现是其余部分,但这是关于总体思路。

我不确定您应该如何检查新数据,因为我对应用程序的细节没有足够的了解;但这对你来说可能是一个开始。

【讨论】:

  • 抱歉,这不是一个选项。我们确实需要图表至少更新 100 次/秒。令人讨厌的是,这在单线程以及 Windows 窗体(使用多线程!)中都可以正常工作
  • 尝试了不同的方法。这是否更适合您的模型?
  • 虽然这可能不是我最喜欢的解决方案,但它至少给了我一个选择。使用 DispatcherTimer,图表每 10 毫秒刷新一次。但是,当不是绝对必要时,我不喜欢在我的代码中使用计时器。我现在正在考虑使用 WindowsFormsHost 和“旧的”Windows Forms 图表控件,因为它在更新时不会抱怨线程。
  • 很高兴我至少可以帮助你。
  • 这无济于事,因为图表仍将仅以显示器的最大频率显示,即 60 赫兹(如果您使用的是标准平板显示器)。
【解决方案2】:

你的要求太疯狂了——你真的不需要每秒 100-200 次更新,尤其是屏幕通常以每秒 60 次更新的速度运行。反正人们不会看到他们。

  • 将新数据输入队列。
  • 为调度程序触发 / 上的拉动事件。
  • 清理队列中的数据(淘汰双打,最后一个有效获胜)并将它们放入。l

每秒 30 次更新就足够了 - 人们不会看到差异。在我这样做之前,我在使用 T&S 的高负载下对一些财务数据有执行问题 - 现在图表看起来更好了。

尽可能少地移动 Dispatcher。

【讨论】:

    【解决方案3】:

    我仍然想知道,当您的显示器甚至无法以那么快的速度显示图表时,您为什么要以每秒 200 次的速度更新图表。 (请记住,普通平板显示器的更新率为 60 fps)

    当您每秒只能看到 60 次更新时,每秒更新 200 次有什么用? 您不妨批量传入数据并以 60 fps 更新图表,因为无论如何您都无法看到差异。

    如果它不仅仅是显示数据,而是你正在用它做其他事情 - 假设你正在监视它以查看它是否达到某个阈值 - 我建议将系统拆分为 2部分:一部分以全速监控,另一部分以显示器可以处理的最大速度独立显示:60 fps。

    所以,请告诉我们您为什么要更频繁地更新 ui 控件,而不是显示给用户。

    【讨论】:

      【解决方案4】:

      WPF 绘图发生在单独的线程中。根据您的图表复杂性,您的 PC 必须有一个超级下降的视频卡才能跟上每秒 100 帧的速度。 WPF 使用 Direct3D 在屏幕上绘制所有内容,并在 Vista 中添加了为此优化的视频驱动程序(在 Windows 7 中进行了改进)。因此,在 XP 上,您可能会因为在设计不佳的操作系统上的高数据输出率而遇到麻烦。

      尽管如此,我认为没有理由以每秒 30-60 帧以上的速度将信息打印到屏幕上。 来吧!即使是FPS射击游戏也不需要玩家如此强烈的反应。你想告诉我,你可怜的图表可以吗? :) 如果通过这种输出,您会产生一些副作用,而这正是您真正需要的,那么情况就完全不同了。然后告诉我们更多关于这个问题的信息。

      【讨论】:

      • 即使你以某种方式管理每秒 100 次更新,但如果你的显示器每秒只刷新 60 次,那也毫无用处!
      • 另外,记录在案的用于 PC 平台的生产视频卡上的最高 DAC 频率是 550 MHz,因此您甚至接近理论边缘。确保您的显卡 RAMDAC 具有足够的时钟频率。
      • 有趣的是,你们所有人都专注于我而不需要 100Hz 更新。只有 Pieter 试图帮助我解决问题本身,提供一些可能的解决方案。谢谢彼得!
      • 是的。我们都在向您解释如何不应该尝试用叉子吃汤。我们告诉“请拿勺子!”。但你没有。
      • 我们的意思是,您似乎正在尝试为不可能成为您的问题的事情寻找解决方案。没有理由那么快地更新控件,因为您不能那么快地显示它。如果它不是关于显示而是关于监视传入的数据,则应该将逻辑与显示分开。这就是我们要告诉你的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-07
      • 1970-01-01
      相关资源
      最近更新 更多