调度线程饱和-从普通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。有没有合适的方法绑定到以这种速度变化的数据集?
您可以创建所有内容都绑定到的基本/根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>
,其中包含在抑制属性更改通知时更改的属性的名称,并在禁用抑制时迭代该集合。