This is a mirror of official site: http://jasper-net.blogspot.com/

How can I propagate changes across threads?

| Tuesday, March 15, 2011
I hope you didn’t get your hopes up too much when you read the title for this post. This time, instead of showing off what we support in our platform, I will explain to you what we don’t. The scenario I have in mind is when you want to bind a control in the UI thread to a collection or property that is modified in a different worker thread. My goal for this post is to tell you what works today and what doesn’t, and although no good workaround exists, I will discuss some ideas around this topic.

Here is the quick version of this post:

We do not support collection change notifications across threads.
We support property change notifications across threads.
Now the long version:

(Disclaimer: I will try to make the content as easy to read as possible, but you will only take full advantage of this post if you’re comfortable with multithreading, the Avalon Dispatcher and some basic data binding.)

Collection change notifications
In this scenario, I have a ListBox that is data bound to a collection of Place objects:

    <ListBox Name="lb"/>
    <Button Click="Throw_Click">Throw</Button>
    
    ObservableCollection<Place> throwPlaces;
    
    private void Throw_Click(object sender, RoutedEventArgs e)
    {
        throwPlaces = new ObservableCollection<Place>();
        AddPlaces(throwPlaces);
        lb.ItemsSource = throwPlaces;
        lb.DisplayMemberPath = "Name";
        (…)
    }
    
    private void AddPlaces(ObservableCollection<Place> places)
    {
        places.Add(new Place("Seattle", "WA"));
        places.Add(new Place("Redmond", "WA"));
        places.Add(new Place("Bellevue", "WA"));
        (…)
    }

Pretty simple. Next, I want to make sure that any changes to my collection are propagated to the UI. Typically, if you are using ObservableCollection<T>, this comes for free because it already implements INotifyCollectionChanged. However, this time I want to change the collection from a different thread:

    Thread workerThread1;
    
    private void Throw_Click(object sender, RoutedEventArgs e)
    {
        (…)
        workerThread1 = new Thread(new ThreadStart(CrashMe));
        workerThread1.Start();
    }
    
    void CrashMe()
    {
        throwPlaces.RemoveAt(0);
    }

Unfortunately, this code results in an exception: “NotSupportedException – This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.” I understand this error message leads people to think that, if the CollectionView they’re using doesn’t support cross-thread changes, then they have to find the one that does. Well, this error message is a little misleading: none of the CollectionViews we provide out of the box supports cross-thread collection changes. And no, unfortunately we can not fix the error message at this point, we are very much locked down.

Read more: Bea Stollnitz

Posted via email from Jasper-net

0 comments: