6

I am gathering data in a separate Task and I want to data bind the result to a GUI component using an ObservableCollection<>. So my code goes something like this:

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;
    });
  });
}

The data is fetched from a component doing some HTTP requests. The error I am getting is:
Must create DependencySource on same Thread as the DependencyObject.

I am using the MVVM Light toolkit framework. I also tried to send the result as a message, but that ended up in the same error message. Any ideas or pointers?

EDIT: Here's the issue:

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; }
}

I changed the BitmapImage to a byte[] data type.

H.B.
  • 166,899
  • 29
  • 327
  • 400
Magnus Johansson
  • 28,010
  • 19
  • 106
  • 164
  • If your task is supposed to be happening in the background so that it doesn't lock up the UI it seems odd that the first thing you do is Invoke back into the UI thread - won't this block all UI input while the _htmlParser is fetching the data? – Martin Harris Sep 02 '10 at 09:26
  • @Martin, you are raising a very good point. When I put the question together, I quickly simplified the code. I have now updated the question with a better code flow. – Magnus Johansson Sep 02 '10 at 10:04

2 Answers2

4

Can you try to replace the Dispatcher.CurrentDispatcher into Application.Current.Dispatcher not sure about this though

nathan_hc
  • 442
  • 4
  • 8
1

The exception you're getting ("Must create DependencySource on same Thread as the DependencyObject") indicates that something's being created on a background thread and used on the UI thread. Are there any UI controls being created and stored in the collection for use by the UI?

I see that the ObservableCollection itself is being created on a background thread, but I don't think that's the issue -- unfortunately I'm not in the office to code and confirm that.

Ragoczy
  • 2,907
  • 1
  • 19
  • 17
  • Correct. In my MyItem class I had a BitmapImage property, which in the end inherits from the DependencyObject class. Changing that to a byte[] data type instead fixed the issue. – Magnus Johansson Sep 02 '10 at 13:17