【问题标题】:Does unnecessary NotifyPropertyChanged calls cause performance issues?不必要的 NotifyPropertyChanged 调用会导致性能问题吗?
【发布时间】:2011-05-17 15:45:51
【问题描述】:

在我的新 WPF 应用程序中,我重用了一个模型类。在该模型类中,所有属性在其设置器中触发 NotifyPropertyChanged。在我的应用程序中,我真的没有为个人财产解雇 INPC 的用例。 我需要知道,如果我保留当前架构,其中单个属性每次更改时都会触发 INPC,是否会导致任何性能影响?在不需要时让个别属性触发 INPC 是否有意义?

【问题讨论】:

  • 您是否确定您确实存在可能是INotifyPropertyChanged订阅导致的性能问题?如果不是,这是premature optimization 的示例
  • @casperOne:是的。但是,由于 INotifyPropertyChanged 是一种常用模式,因此这是一个普遍感兴趣的问题。
  • 相关 - 每当使用数据绑定以防止内存泄漏时,您都应该实现 INotifyPropertyChangedstackoverflow.com/a/27069346/492

标签: c# wpf mvvm inotifypropertychanged


【解决方案1】:

一般来说,只要您运行一段您不必运行的代码,就有可能导致性能问题。

根据经验,当您为属性编写 setter 而不仅仅是设置支持字段并引发更改事件时,您应该在通知之前检查相等性,从而避免不必要的更新.

例如:

public int MyInteger 
{
   get { return this._myInteger; }
   set { 
         if ( value != this._myInteger )
         {
            this._myInteger = value;
            RaiseChangedEvent("MyInteger");
         }
      }

您还应该检查 RaiseChangedEvent 方法中的附加事件,因此如果没有侦听器,您不会抛出空引用异常,也不会不必要地进行调用:

private void RaiseChangedEvent(string propertyName)
{
   var changedHandler = this.PropertyChanged ;
   if ( changedHandler != null )
      changedHandler(this, new PropertyChangedEventArgs( propertyName ) );
}

【讨论】:

  • 是的。说得通。只是想证实我的猜想。看起来如果我不能删除那些 INPC 调用,我可能会添加一些额外的检查。我会尝试稍后检查 changeHandler。我现在没有它。
  • 您还可以将 PropertyChangedEventArgs 的实例保存在静态字段中,这样您就无需每次都重新创建它们。在 Cinch 框架中看到了这个
  • 是的,有很多方法可以优化这一点,我喜欢传递一个委托而不是一个字符串,以避免造成雷区。
【解决方案2】:

当触发 PropertyChanged 事件时,您应该有如下内容:

private void NotifyPropertyChanged(string name) {
    if (PropertyChanged != null) {
        PropertyChanged(this, new PropertyChangedEventArgs(name));
    }
}

如果 PropertyChanged 为 null,则没有任何侦听器附加到您的事件。因此,对性能的影响很小(如果有的话)。

如果有监听器,那么您需要引发事件,以便他们收到更改通知。

【讨论】:

  • 也写成PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
【解决方案3】:

如果这些对象的事件没有附加任何内容,那么应该不会有太大的性能损失,尽管您仍在执行代码,因此与删除它。

【讨论】:

  • 我的数据网格确实绑定到了整个对象。我确实希望对这些对象进行实时更新。但这些更新大多涉及用新记录替换记录。
  • 对于你的数据网格,网格正在监听一个可观察的排序列表,所以如果你用另一个记录替换一个记录,应该通过在列表中用另一个对象替换一个对象来完成(与设置现有对象的每个属性相比)。这将引发一个事件。怎么样,您将让侦听器在网格的可见区域中侦听每个对象的每个属性,但是如果更改是在完全替换的脉络中,则在这些情况下不应触发这些属性事件。
【解决方案4】:

INotifyPropertyChange 是一个事件,它会在绑定到控件的属性发生任何更改(这里的更改是指值更改)时触发,理想情况下它取决于这些事件中编写的代码,否则它不是开销,但它是为班级的每个属性设置 INotifyPropertyChange 并不是一个好习惯

【讨论】:

    猜你喜欢
    • 2015-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-14
    • 1970-01-01
    • 2017-12-10
    • 2018-12-21
    相关资源
    最近更新 更多