MVVM和多线程

时间:2011-01-05 14:03:05

标签: wpf multithreading mvvm

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

与往常一样,为简单起见,我们有一个Model类,ViewModel类和View类。 Model有一个Collection和一个字符串属性。

1)用户触发长时间运行的后台任务。视图触发ViewModel。可以使用ViewModel轻松管理,例如,使用BackgroundWorker

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

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

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

我想我已经回答了我自己的问题。也许不是。我的模型确实知道线程,所以也许使用科林早些时候提出的IMarshalInvoker想法来标记它们是否有礼貌?

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

1 个答案:

答案 0 :(得分: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);
    }
}

如果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 :)
}

最后,您需要让ObservableCollection在从工作线程更新时发挥出色。这是WPF的一个非常常见的问题,我建议您回答这个问题的解决方案:ObservableCollection and threading