【问题标题】:How to handle ObservableCollection<> result from a parallelized Task in MVVM?如何处理 MVVM 中并行任务的 ObservableCollection<> 结果?
【发布时间】:2011-04-07 05:41:11
【问题描述】:

我正在一个单独的任务中收集数据,我想使用 ObservableCollection&lt;&gt; 将结果数据绑定到 GUI 组件。所以我的代码是这样的:

private ObservableCollection<MyItem> _items;
public ObservableCollection<MyItem> Items
{
  get { return _items; }
  set
  {
    if (_items.Equals(value))
    {
      return;
    }
    _items = value;
    RaisePropertyChanged("Items");
  }
}

private void LoadData()
{
  Task task = Task.Factory.StartNew(() =>
  {
    ObservableCollection<MyItem> itms = _htmlParser.FetchData(...);

    Dispatcher.CurrentDispatcher.Invoke((Action)delegate
    {
      Items = itms;
    });
  });
}

数据是从执行一些 HTTP 请求的组件中获取的。我得到的错误是:
Must create DependencySource on same Thread as the DependencyObject.

我正在使用 MVVM Light 工具包框架。我也尝试将结果作为消息发送,但最终出现相同的错误消息。有什么想法或建议吗?

编辑:这是问题:

public class MyItem
{
  public string Id { get; set; }
  public string Name { get; set; }
  public BitmapImage Image { get; set; }  // <--- A big No No because it inherits from the DependencyObject
  public Uri Uri { get; set; }
}

我将BitmapImage 更改为byte[] 数据类型。

【问题讨论】:

  • 如果您的任务应该在后台发生,这样它就不会锁定 UI,那么您要做的第一件事就是调用回 UI 线程似乎很奇怪 - 这不是吗在 _htmlParser 获取数据时阻止所有 UI 输入?
  • @Martin,你提出了一个很好的观点。当我把问题放在一起时,我很快简化了代码。我现在用更好的代码流更新了这个问题。

标签: c# multithreading data-binding mvvm mvvm-light


【解决方案1】:

您能否尝试将Dispatcher.CurrentDispatcher 替换为Application.Current.Dispatcher,但对此不确定

【讨论】:

  • 好吧,我会被诅咒的。没意识到区别。谢谢。
  • 将代码更改为更好的调用模式后(请参阅更新),您的建议不再有效。
【解决方案2】:

您得到的异常(“必须在与 DependencyObject 相同的线程上创建 DependencySource”)表明正在后台线程上创建某些内容并在 UI 线程上使用。是否有任何 UI 控件正在创建并存储在集合中以供 UI 使用?

我看到 ObservableCollection 本身是在后台线程上创建的,但我认为这不是问题 - 不幸的是,我不在办公室进行编码和确认。

【讨论】:

  • 正确。在我的 MyItem 类中,我有一个 BitmapImage 属性,它最终继承自 DependencyObject 类。将其更改为 byte[] 数据类型可以解决问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-18
  • 2017-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多