调度线程饱和-从普通MVVM中寻找设计模式变化

本文关键字:MVVM 寻找 设计模式 变化 线程 调度 | 更新日期: 2023-09-27 18:00:23

也许"饱和"是个错误的词,但实际上我的Dispatch线程一直很忙,因为我有大量的UI更新。

在这之前,我一直遵循(并喜欢)我所说的香草MVVM设计模式。我用来指导我的开发的关键资源列在MVVM的优秀公认答案中:从头到尾的教程。

具体而言;

  • Jason Dolinger关于模型视图视图模型的演示

粗略架构

我有以下名称空间;

  • 数据
    • 连接到外部服务并侦听更新
    • 每隔1-2秒接收一包更新
    • 单个"调度源",用于为应用程序调度调度程序上的所有ViewModel更新
  • ViewModel
    • UI线程上创建的所有类和所有方法都在UI线程上调用
    • 处理从数据到GUI代码的所有转换
  • 查看
    • Xaml类
    • 很少(如果有的话)代码隐藏或转换逻辑
    • 唯一重量级的组件是XCeed DataGrid,它在内部对数据进行排序

数据集

在其高峰期,Dispatching源每分钟在调度线程上调度65000个事件。

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

问题

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

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

对于这种情况,有一个好的设计模式吗

我认为这个问题并不是我独有的,我希望有比我聪明得多的人试图设计出一个解决方案。很明显,我需要

多重量和轻重量VS不常见和重重量

我可以在后台线程中进行更改,然后在UI线程上运行的批处理方法中更新4000个绑定。

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

底线

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

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

调度线程饱和-从普通MVVM中寻找设计模式变化

您可以创建所有内容都绑定到的基本/根ViewModel,并让它实现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);
            }
         }
      }
   }

如果不了解更多关于你的申请,很难说。如果这样做会触发数千个绑定,您可能需要维护一个HashSet<string>,其中包含在抑制属性更改通知时更改的属性的名称,并在禁用抑制时迭代该集合。