【问题标题】:Invoking OnPropertyChanged NOT on the UI Thread - Performance Degradation [duplicate]不在 UI 线程上调用 OnPropertyChanged - 性能下降 [重复]
【发布时间】:2018-04-23 09:15:01
【问题描述】:

我已经解决了一些 UI 更新缓慢的问题,我想听听为什么我的代码修改实际上提高了性能。

我开发了一个 WPF 应用程序,MVVM 架构。 我在视图模型中有一个属性:

public DateTime MyDate
    {
        get
        {
            return _myDate;
        }
        set
        {
            _myDate= value;
            OnPropertyChanged()
            OnPropertyChanged(() => MyDateFormatted);
        }
    }

MyDateFormatted 如下所示:

public string MyDateFormatted
    {
        get { return _myDate.ToString("MMMM dd, yyyy"); }
    }

MyDate 的设置器不会发生在 UI 线程上。 MyDateFormatted 的 getter 发生在 UI 线程上,因为正如我所读到的,WPF 会自动将属性更改编组到 UI 线程。

Making sure OnPropertyChanged() is called on UI thread in MVVM WPF app

确实,用户界面已更新,但非常缓慢。 曾经,我手动附加了 OnPropertyChanged(() => MyDateFormatted); 到 UI 调度程序,通过调用包围它: Application.Current.Dispatcher, UI 现在可以按照我想要的速度更新,并且性能得到了显着提升。你能解释一下为什么吗?谢谢!

【问题讨论】:

  • 您多久更新一次该属性以导致性能问题?
  • @Evk 非常非常非常频繁。像每毫秒一样
  • 对于您发布的两种实现,很明显您不需要调用方法OnPropertyChanged 两次。这两个调用的作用相同——第一个调用使用 .NET 4.5+ 功能来获取属性名称,第二个调用使用表达式(肯定更慢)功能。只调用一次,我更喜欢第一个。

标签: c# wpf multithreading


【解决方案1】:

一个可能的原因是Dispatcher.Invoke 会限制(减慢)更新MyDate 的算法,并允许 UI 线程跟上这些更新。假设你有以下代码:

new Thread(() => {
    while (true) {
        this.MyDate = DateTime.UtcNow;
    }
})
{ 
   IsBackground = true 
}.Start();

这是一种极端情况,值会不断更新,没有任何延迟。当MyDate 上的OnPropertyChanged 被调用时,WPF 将通过Dispatcher.BeginInvoke(注意Begin)对UI 线程上的绑定更新进行排队。

在这种极端情况下,它会非常快地淹没 UI 线程队列,并且 UI 线程将无法跟上待处理的待处理操作的数量。这是因为 Dispatcher.BeginInvoke 不会减慢 while (true) 线程,因为它是异步的。

现在假设您将 this.MyDate = DateTime.UtcNow 包裹在 Dispatcher.Invoke 中。 Invoke 是同步的,直到 UI 线程真正执行此操作才会返回。现在循环受到限制并且运行速度要慢得多,因为更新 UI 现在是循环的一部分,并且 UI 操作队列不会无限制地增长。

在现实生活场景中,值得自己限制 UI 更新。因此,如果您有一个紧密的循环 - 不要在每次迭代时更新 UI 绑定属性,而是在每次 X(100、1000)次迭代时更新,以免给 UI 线程带来太多负担(无论如何,太快的更新都是无用的,因为人眼无论如何都无法捕捉到您的 1ms 更新)。如果您没有太多理由(用于执行 UI 更新)减慢算法速度这一事实,您的“修复”可能没问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-07
    • 1970-01-01
    • 2012-08-10
    相关资源
    最近更新 更多