Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 未在UI线程上调用OnPropertyChanged-性能下降_C#_Wpf_Multithreading - Fatal编程技术网

C# 未在UI线程上调用OnPropertyChanged-性能下降

C# 未在UI线程上调用OnPropertyChanged-性能下降,c#,wpf,multithreading,C#,Wpf,Multithreading,我已经解决了一些UI更新缓慢的问题,我想听听为什么我的代码修改实际上提高了性能 我开发了一个WPF应用程序,MVVM架构。 我在视图模型中有一个属性: public DateTime MyDate { get { return _myDate; } set { _myDate= value; OnPropertyChanged()

我已经解决了一些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线程

的确,用户界面得到了更新,但速度非常缓慢。 有一次,我手动附加了 OnPropertyChanged(()=>MyDateFormatted); 通过在UI Dispatcher周围使用invoke: Application.Current.Dispatcher,
用户界面现在可以按照我的要求快速更新,性能也有了显著提高。你能解释一下原因吗?谢谢大家!

一个可能的原因是
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中<代码>调用
是同步的,在UI线程实际执行此操作之前不会返回。现在循环被限制,运行速度慢得多,因为更新UI现在是循环的一部分,UI操作队列在没有绑定的情况下不会增长


在现实生活中,你自己控制UI更新是值得的。所以,如果你有一个紧密的循环-不要在每次迭代时更新UI绑定属性,而是在每次X(100,1000)迭代时更新,这样就不会给UI线程带来太多负担(太快的更新是没有用的,因为人眼无论如何都无法捕捉到你的1ms更新)。如果您对这样一个事实感到满意,那么您的“修复”可能是可以的:它会在没有太多理由的情况下减慢您的算法(用于执行UI更新)。

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