Parallel ObservableCollection in Silverlight 5

I need a thread-safe (parallel) version of ObservableCollection in Silverlight 5. I am struggling to find a way to create one given the lack of multithreading support in SL5 (no ReaderWriterLock, no Collections.Concurrent to speak, etc.).

I need a collection to support the binding of an interface when updated by another thread. Unacceptable for me to send all my updates to the UI thread when the process is running in the background. Ideally, a background process can update the collection for free as needed, and the UI is notified when changes are made. This is possible since .NET 4 and I found ways to accomplish this for WPF but nothing for SL. I can't use WPF examples because they rely on ReaderWriterLock, which AFAIK is missing from SL5.

Any direction and / or examples are appreciated.

UPDATE

After the (required) asynchronous communication pattern in Silverlight is used, the "callback" method or handler is executed on a different thread. Using TPL (as we are) this is a Continuation task.

Since this code runs on a different thread, any assertions that affect the ObservableCollection must be redirected back to the UI thread. This means that the process logic and time are now consuming the resources of the UI thread.

The point of concurrent collections in .NET is to allow producers and consumers to work on different threads, but work seamlessly with the shared data in the collection. "Producers" in an SL client application will be an asynchronous callback or task continuation with "consumers" being the user interface that is bound to the collection.

+3


source to share


1 answer


I also ran into this problem on multiple occasions, which made me follow the same road you are looking at. There is a library that helped me a lot with this task:

http://ch.codeplex.com/

I have implemented my own ConcurrentObservableCollection using TinyReaderWriterLock and have implemented IList, INotifyCollectionChanged, INotifyPropertyChanged

I used this blog post as a starting point. http://www.deanchalk.me.uk/post/Thread-Safe-Dispatcher-Safe-Observable-Collection-for-WPF.aspx

In my version, I allow all calls to be made on the calling thread, and only marshal the INotifyCollectionChanged and INotifyPropertyChanged calls back to the UI thread like this:

public void Add(T item)
{
    mSyncLock.LockForWriting();
    innerCollection.Add(item);
    mSyncLock.ReleaseForWriting();

    var index = IndexOf(item);

    OnNotifyPropertyChanged(COUNT_PROPERTY);
    OnNotifyPropertyChanged(INDEXER_PROPERTY);
    OnNotifyCollectionChanged(NotifyCollectionChangedAction.Add, item, index); // This is an overload of OnNotifyCollectionChanged(NotifyCollectionChangedEventArgs e)
}

      



Where

protected virtual void OnNotifyCollectionChanged(NotifyCollectionChangedEventArgs e)
{
    if (CollectionChanged == null) return;

    ThreadSafeInvoke(() => CollectionChanged(this, e));
}

      

and

private static void ThreadSafeInvoke(Action action)
{
    if (Deployment.Current.Dispatcher.CheckAccess())
    {
        action.Invoke();
    }
    else
    {
        Deployment.Current.Dispatcher.BeginInvoke(action);
    }
}

      

This worked well for me. There is a slight performance penalty associated with locking, but this is not important for most applications.

+4


source







All Articles