MVVM和多线程

Ian*_*Ian 6 wpf multithreading mvvm

对,坚持MVVM焦点一分钟,有少数可能发生线程的场景:

像往常一样,为简单起见,我们有一个Model类,ViewModel类和View类.Model具有Collection和string属性.

1)用户触发长时间运行的后台任务.视图触发ViewModel.可以使用ViewWorker轻松地使用ViewModel进行管理

2)线程更新模型,ViewModel通过模型更改通知.

之前我们已经讨论过使用INotifyChanged来通知从Model到ViewModel的更改.DependencyProperty系统似乎为您编组这些正确的线程.

对于ObservableCollections,这不起作用.因此,如果我的模型的公共面是单线程的(不喜欢,模型为什么要知道线程),或者我会在ViewModel中复制模型的某些部分(例如上面的Collection)以确保对模型进行修改正确的线程?

我想我已经回答了我自己的问题.也许不是.我的模型不知道线程,因此或许只有礼貌对待markshal回用科林早期酝酿的IMarshalInvoker想法?

我的一些问题是我认为MVVM是另一个MVC变种,而且从历史上看,我很乐意使用像MVP,MP,MVC这样的术语几乎可以互换,因为我知道什么对GUI技术起作用(通常是winforms) V端.当我说MVVM时,我特别在寻找有关WPF和WPF特定弱点的实用建议.我希望这能解释我的问题的性质以及我问他们的原因.

Jon*_*Jon 6

我不认为在模型中全力以赴并实现集合是一个非常好的主意ObservableCollection,因为这会以一种仅对WPF有用的方式"污染"您的模型.

INotifyPropertyChanged 没关系,因为:

  • 在许多情况下,具有"收听"能力是有用的.
  • 它可以从几乎任何.NET代码中使用,而不仅仅是WPF.
  • 如果要序列化模型,它不会给您带来任何麻烦.

所以,我建议不要让你的模型知道线程.让您的ViewModel了解线程,如下所示:

class Model {
    List<Widget> Widgets { get; private set; }
}

class ModelViewModel {
    ObservableCollection<Widget> Widgets { get; private set; }

    ModelViewModel(Model model) {
        this.Widgets = new ObservableCollection<Widget>(model.Widgets);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果Widget是一个引用类型和实现INotifyPropertyChanged(大约100%的时间),这会让你大部分时间:

  • 对任何小部件的更改将自行进行,model并立即反映绑定
  • 对集合的更新将立即反映绑定

仍然存在无法model直接对集合(添加和删除项目)进行更新的问题.但可以安排:

ModelViewModel(Model model) {
    this.Widgets = new ObservableCollection<Widget>(model.Widgets);
    this.Widgets.CollectionChanged += this.PropagateChangesToModel;
}

void PropagateChangesToModel(object sender, NotifyCollectionChangedEventArgs e) {
    // do what the name says :)
}
Run Code Online (Sandbox Code Playgroud)

最后,您需要通过ObservableCollection从工作线程更新来发挥良好作用.这是WPF的一个非常常见的问题,我将为您提供一个解决方案的答案:ObservableCollection和threading.