【问题标题】:Can I Create or Fill ViewModels and ObservableCollection in a Background Thread?我可以在后台线程中创建或填充 ViewModel 和 ObservableCollection 吗?
【发布时间】:2016-10-05 15:49:07
【问题描述】:

我有一个 MVVM (C#/WPF) 应用程序,想在后台线程中创建和填充我的 ViewModel(使用 INotifyPropertyChange)和 ObservableCollections。

如果这样做,我会得到一个异常:“必须在与 DependencyObject 相同的线程上创建 DependencySource。”

我知道如何使用 Dispatcher 在 UI 线程中移动操作。但我不清楚什么必须转移到 UI 线程。我有以下5个案例。

  1. var vm = new ViewModel(); // implements INotifyPropertyChange
  2. vm.Name = "name"; // Fires PropertyChange
  3. var oc = new ObservableCollection<ViewModel>();
  4. oc.Add(vm);
  5. var oc2 = new ObservableCollection<ViewModel>(list); // while list is List of ViewModel

【问题讨论】:

  • “我不清楚什么必须移动到 UI 线程”:从引发异常的任何内容开始。
  • 我认为如果您在后台线程上修改对象之前freeze 对象,您可以这样做。 Check out this post
  • “我有以下 5 个案例”——这是什么意思。使用后台线程的代码在哪里,是哪一行抛出错误?
  • 这些行之一不会直接引发异常。它是由“消费代码”抛出的

标签: c# wpf multithreading mvvm


【解决方案1】:

您不能在非Dispatcher 线程上调用ObservableCollection<T>.Add()

您可以在非Dispatcher 线程上创建ObservableCollection<T>

只要您在构造函数中没有任何 Dispatcher-only 调用,您在哪个线程上创建 ViewModel 对象并不重要。

关于 PropertyChanged 事件的评论更新:

您需要在Dispatcher 线程上引发PropertyChanged 事件,以便处理它们。我发现在这些情况下,只需将事件的引发封装在 Dispatcher.Invoke() 调用中是很有用的。

针对具体案例的答案更新

  • 案例 1:只要构造函数中没有Dispatcher 特定的调用,就可以在任何线程上。
  • 案例 2:如果您希望事件由任何绑定的控件处理,则应在 Dispatcher 上引发。
  • 案例 3:可以在任何线程上。
  • 案例 4:必须在 Dispatcher 上。
  • 案例 5:可以在任何线程上。

【讨论】:

  • 所以 - 案例 1(具有空构造函数)可以在非调度程序线程中运行,而案例 2 必须在调度程序线程中运行?而 PropertyChange() 只调用一个调度程序?
猜你喜欢
  • 2012-06-22
  • 1970-01-01
  • 2020-08-26
  • 2017-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多