C# 调度线程饱和-从MVVM中寻找设计模式的变化

C# 调度线程饱和-从MVVM中寻找设计模式的变化,c#,wpf,performance,mvvm,C#,Wpf,Performance,Mvvm,也许“饱和”是一个错误的词,但本质上我的调度线程一直很忙,因为我的UI更新太多了 在此之前,我一直遵循(并享受)我称之为香草MVVM设计模式。我用来指导我的发展的关键资源列在我的优秀公认答案中 具体而言 粗略架构 我有以下名称空间 资料 连接到外部服务并侦听更新 每1-2秒接收一个更新数据包 单个“调度源”,用于调度应用程序调度程序上的所有ViewModel更新 视图模型 在UI线程上创建的所有类和所有方法都在UI线程上调用 处理从数据到GUI代码的所有转换 看法 Xaml类

也许“饱和”是一个错误的词,但本质上我的调度线程一直很忙,因为我的UI更新太多了

在此之前,我一直遵循(并享受)我称之为香草MVVM设计模式。我用来指导我的发展的关键资源列在我的优秀公认答案中

具体而言

粗略架构

我有以下名称空间

  • 资料
    • 连接到外部服务并侦听更新
    • 每1-2秒接收一个更新数据包
    • 单个“调度源”,用于调度应用程序调度程序上的所有ViewModel更新
  • 视图模型
    • 在UI线程上创建的所有类和所有方法都在UI线程上调用
    • 处理从数据到GUI代码的所有转换
  • 看法
    • Xaml类
    • 很少(如果有)代码隐藏或转换逻辑
    • 唯一的重量级组件是内部排序数据的
数据集

在峰值时,调度源每分钟在调度线程上调度65000个事件

每秒1000个事件,其中每个事件将导致约4个绑定的更改。很少有逻辑(但也有一些逻辑)用于确定新值,通常可能会在字符串或哈希查找上进行切换,以查找行背景的颜色

问题

我想现在已经很明显了,但是反应能力很差。有时UI会完全锁定

如果我将负载减半,那么GUI就可以了,所以它不会减少一个数量级,但是如果它能够处理更多数量级的负载,那就更好了

在这种情况下有好的设计模式吗?

我认为这个问题并不是我独有的,我希望有比我聪明得多的人试图想出解决办法。很明显,我需要这样做

多重和轻量化与罕见和重量级的对比

我可以在后台线程中进行更改,然后在UI线程上运行的批处理方法中更新4000个绑定,而不是在UI线程上调度1000个单独的更新(方法调用),每个更新4个绑定

这将减少分派方法调用所花费的开销,但可能会在执行其中一个批处理时锁定UI。不理想

底线

我不知所措,我觉得我需要对后台线程上的对象进行所有更改,然后每隔一段时间(每两秒?)轮询状态,以便UI保持响应


这听起来不像是我所熟悉和喜爱的MVVM。是否有合适的方法绑定到以这种速度更改的数据集?

您可以创建所有内容都绑定到的基本/根视图模型,并让它实现
INotifyPropertyChanged
——但如果任何属性已更改,则只能使用计时器触发
PropertyChanged
事件


属性更改时->将其添加到唯一的“脏”列表中。计时器超时->触发该列表中的所有事件,重置列表。

Kieren Johnstone在正确的轨道上。我认为答案可能更简单,根本不需要计时器

在视图模型基类中实现以下成员。在更新开始时,在视图模型对象上设置数据服务
SuppressPropertyChanged
,并在更新完成后将其清除

protected void OnPropertyChanged(string propertyName)
{
   if (SuppressPropertyChanged)
   {
      return;
   }
   PropertyChangedEventHandler h = PropertyChanged;
   if (h != null)
   {
      h(this, new PropertyChangedEventArgs(propertyName);
   }
}

private bool _SuppressPropertyChanged;

public bool SuppressPropertyChanged
{
   get { return _SuppressPropertyChanged; }
   set
   {
      if (_SuppressPropertyChanged != value)
      {
         _SuppressPropertyChanged = value;
         if (!_SuppressPropertyChanged)
         {
            PropertyChangedEventHandler h = PropertyChanged;
            if (h != null)
            {
               // using null tells the listener to refresh all properties
               h(this, new PropertyChangedEventArgs(null);
            }
         }
      }
   }
如果不了解更多关于您的应用程序的信息,很难说。如果这样做会触发数千个绑定,则可能需要维护一个
哈希集
,其中包含在属性更改通知被抑制时更改的属性的名称,并在禁用抑制时在该集上迭代