gpt4 book ai didi

c# - INotifyPropertyChanged 在处理大量数据时陷入困境

转载 作者:太空宇宙 更新时间:2023-11-03 18:03:52 25 4
gpt4 key购买 nike

我有一个 HID 设备,我以大约 200hz-600hz 的频率与之通信,并将数据解释为表示 HID 设备属性的类对象。该类在其属性上实现了 INotifyPropertyChanged,并且由于通信速度的原因,我认为处理队列陷入困境,因为几分钟后控件似乎变得滞后和“帧”。

.net 中是否存在可以帮助解决此类问题的方法,也许是事件处理程序池或某种队列?

不幸的是,没有我的 HID 设备,我不确定我的代码是否对任何人复制有任何用处,但我将包含几个相关的片段来展示我的实现:

public enum DataEvents { onNone = 0, onStatus = 1, onInput = 2, onOutput = 4, onReport = 8};
public class Controller: INotifyPropertyChanged, IDisposable, INotifyDisposed
{
public event PropertyChangedEventHandler PropertyChanged;
public event EventHandler Disposing;
public event EventHandler Disposed;
public event EventHandler ReportReceived;

internal void callPropertyChanged(string PropertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}

internal void callReportReceived()
{
ReportReceived?.Invoke(this, EventArgs.Empty);
}

public bool Touch1
{
get { return _Touch1; }
private set { if (value != _Touch1) { _Touch1 = value; if (RaiseUpdateEvents.HasFlag(DataEvents.onInput)) callPropertyChanged("Touch1"); } }
}
private bool _Touch1 = false;

//There are many more properties but all of them follow this pattern, and have several different types
}

我的对象是从轮询 HID 设备以获取报告的循环中的 System.Threading.Thread 填充的,HID 设备读取方法是阻塞调用,因此循环不是死循环,并且受限于设备的数据速率,通常为 200hz-600hz。

编辑:值得注意的是,我对 WPF 绑定(bind)特别感兴趣。

最佳答案

在 WPF 中处理近乎实时的系统时(过去 6 年我一直在研究它们),您有几个选择。首先,我将列出一些值得深思的地方:

  • 要通过一个事件更新所有 WPF 绑定(bind),请使用 string.Empty 作为您的属性名称。
  • 您的问题可能不完全是事件造成的。 WPF 有很多影响内存管理的问题。

所以您要问的问题是,用户需要多久查看一次更改?人类的视觉暂留是 1/10 秒,即 100 毫秒。任何比这更频繁的更新都会被浪费,但通常情况下,即使是太频繁了。

每秒一个事件?

在我的场景中,我们确定我们只需要每秒更新一次屏幕上的所有内容。尽管我们每秒最多接收 12 次数据(每个样本 83 毫秒),但我们收集并平均了数据以使其平滑。它让我们的用户更好地了解正在发生的事情。

  • 我们将 View 模型架构为使用主计时器每秒调用一次 Update() 方法。
  • 模型实现了 INotifyPropertyChanged 以避免 binding memory leak ,但只引发了一个带有 string.Empty 的属性更改事件以导致 UI 刷新

最小化对象创建

花在垃圾收集上的每一毫秒都是用户无法与您的应用程序交互的明显时间。每次引发事件时,都必须创建要发送的事件对象。虽然从技术上讲,您可以创建一次事件对象并引发相同的实例,但 WPF 可以在多个地方为您创建对象实例。这些是您需要注意的事项:

  • DataTemplate 本质上是为每个您想要模板化的对象创建一个新模板。尽可能尝试使用虚拟化,并尽量减少使用。
  • ResourceDictionary 每次您在控件中声明资源字典时,您都在创建一个新实例。最好将所有合并的资源字典放在 App.xaml 中,而不是在不同的用户控件中继续包含相同的字典。特别是如果您在 DataTemplate
  • 中拥有用户控件
  • ContentPresenter 不是你的 friend 。

进一步解释一下,ContentPresenter 将获取您的对象,在控件的 ResourceDictionary 中查找它的类型以找到要实例化的 DataTemplate为您的数据。当您需要将窗口的特定部分换成另一个控件时,它会很方便,但它确实会带来很大的成本。尽可能减少它的使用。

在后台保持硬件/通信

我们专门设置线程来处理通信和处理需求。这让 UI 保持响应,同时我们可以对数据进行一些 DSP/统计减少。

使用内存分析器

任何时候您需要在显示器上进行近乎实时的更新,您必须特别注意内存的使用。这是我们不得不应对的头号问题。

  • 您的应用程序开始时正常,但一两分钟后它开始降级
  • 确保您没有持有您不希望的对象实例
  • 寻找在垃圾回收事件中幸存下来的对象

关于c# - INotifyPropertyChanged 在处理大量数据时陷入困境,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40284010/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com