为了账号安全,请及时绑定邮箱和手机立即绑定

在UI线程上调用OnPropertyChanged NOT-性能下降

在UI线程上调用OnPropertyChanged NOT-性能下降

C#
繁星点点滴滴 2021-05-04 11:10:09
我已经通过缓慢的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的获取方法发生在UI线程上,因为,正如我所读到的那样,WPF自动将对UI线程的属性更改编组。确保在MVVM WPF应用程序的UI线程上调用OnPropertyChanged()确实,UI已更新,但是非常缓慢。一次,我手动附加了OnPropertyChanged(()=> MyDateFormatted); 到UI Dispacher,通过将其与调用:Application.Current.Dispatcher包围在一起,UI可以立即按我想要的速度进行更新,并且性能得到了极大的改善。你能解释为什么吗?谢谢!
查看完整描述

1 回答

?
喵喵时光机

TA贡献1846条经验 获得超7个赞

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


new Thread(() => {

    while (true) {

        this.MyDate = DateTime.UtcNow;

    }

})

   IsBackground = true 

}.Start();

在极端情况下,值会不断更新而没有任何延迟。发生的是调用OnPropertyChangedon时MyDate,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更新),那么“修复”可能就可以了。


查看完整回答
反对 回复 2021-05-08
  • 1 回答
  • 0 关注
  • 330 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信