3

我们有几个图表显示来自表面 EMG 传感器的过滤数据。此数据通过 TCP 接收并使用事件传播。数据包属于 DataPackets 类型,因此会被过滤掉。我正在使用缓冲区让数据包以 30FPS 的速度通过。我正在使用 Reactive Extensions 收听此事件,如下所示:

Observable.FromEvent<Packet>(h => this.DataService.PacketReceived += h, h=> this.DataService.PacketReceived -= h)
          .OfType<DataPacket>()
          .Buffer(TimeSpan.FromSeconds(1.0 / 30))
          .ObserveOnDispatcher()
          .Subscribe(
              packet => this.ReceiveDataPackets(packet.ToList()),
              err => this.Log.Error("Error subscribing to data packets", err),
              () => this.Log.Info("Finished listening to data packets"));

为了显示 EMG 数据,我们使用 Telerik ChartView。我遇到的问题是数据更新不流畅,图表不稳定。

这可能有几个原因:

  1. Telerik 图表对于每秒 1000 个数据点来说不够快
  2. DispatcherTimer 不会以恒定速率触发
  3. 数据不是以恒定速率接收的

点 1 是通过对输入数据进行采样来解决的,因此图中只有 1000 个点可见。

不幸的是,第2点无法解决。我尝试将优先级提高到渲染,但这根本没有帮助。http://social.msdn.microsoft.com/Forums/en-US/5eea6700-1c79-4da6-9b68-efa480ed3a36/simplify-wpf-dispatcher-calls?forum=rx

第 3 点与第 2 点相关。我尝试使用定时队列来解决这两个问题System.Debug.Stopwatch。DataPackets 包含一个时间戳,这用于让它们在 Dispatcher 线程上以恒定速率通过。我怀疑这不会有太大帮助,因为 DispatcherRate 没有链接到渲染线程的刷新率。

我能做些什么来减少波动?我尝试了 LightningChart Ultimate,它应该要快得多。它确实具有更好的性能,并且不需要进行任何采样,它可以渲染每个数据点。LightningChart 提供的样本运行顺利,但它们在主线程中读取数据。当我在我们的多线程程序中实现他们的图表时,它仍然受到第 2 点和第 3 点的影响(事实上它比 Telerik chartview 贵得多。)

[更新]

经典错误。我的数据源使用 DispatcherTimer 来收集数据。将其更改为 Observable.Interval 极大地提高了性能。

4

2 回答 2

1

不久前,我在图表控制方面也遇到过类似的问题。我也发现大多数图表控件无法处理 1000 多个数据点。我还发现,试图让它每秒重新渲染超过 5-15 次对调度员来说是相当困难的。

我建议你的事情是:

  1. 争取更低的帧速率。您希望每 33 毫秒更新一次图表吗?
  2. 将您的数据集减少到 1000 个点。再次使用数字来查看适用于您的目标规格 PC 和控件/数据模板的内容。这篇旧帖子可能会对您有所帮助。它提供了一种从集合中选择 X 最有用的点进行渲染的方法
  3. 拨回图表上每个点呈现的任何精美动画或额外 UI。如果您要添加更多项目,每个项目都有工具提示、画笔、动画和多余的布局面板,您将支付成本。另请注意,您不仅会在创建它们时支付成本,而且还会在稍后 GC 尝试清除这数千个 UI 对象时支付成本。
  4. 在调度程序上做更少的工作。我知道这并不多,但你可以移动它ToList()并在另一个线程上做。此外,不要发送要处理的空列表(如果适用于您的活动)
  5. 考虑使用D3/DDD 图表。虽然当我审查它们时它们并不好,但从那时起,同事们与它们取得了成功。

    Observable.FromEvent<Packet>(h => this.DataService.PacketReceived += h, h=> this.DataService.PacketReceived -= h)
      .OfType<DataPacket>()
      .Buffer(TimeSpan.FromSeconds(1.0 / 8))  //Reduce the FPS
      .Select(packet=>packet.ToList())        //Reduce work done on dispatcher
      .Where(packet=>packet.Count>0)          //Dont send empty sets to dispatcher
      .ObserveOnDispatcher()
      .Subscribe(
          packet => this.ReceiveDataPackets(packet),
          err => this.Log.Error("Error subscribing to data packets", err),
          () => this.Log.Info("Finished listening to data packets"));
    

我不确定它是否有帮助,但这是演示文稿中一些代码的另一个链接。演示的一部分是关于如何通过 Rx 将数据流式传输到 WPF 图表。你可能会撕掉整个东西。

于 2013-10-07T17:30:58.873 回答
1

我知道这是一个老问题,但它可能会帮助这里的人。

如果您想在 WPF 图表中显示来自传感器的数据,如果您使用标准的开源图表组件或大多数商业供应商(如 Telerik),将会非常慢。

我想推荐我自己的组件:SciChart,它在 WPF 中以毫秒更新显示数百万个点。

SciChart 是一个商业组件,我想透露,是的,我是所有者,但是,在可用性或性能方面,没有任何免费或开源的替代品可以与它相提并论。

请查看页面Why SciChart - the Best WPF Chart,因为它有一些您可以查看的特定性能演示/视频。支持数据多线程更新,可应对1000点/秒。

于 2019-03-07T10:10:10.907 回答