Silverlight 5中的并发ObservableCollection

时间:2012-03-07 21:03:01

标签: silverlight concurrency task-parallel-library silverlight-5.0

我需要在Silverlight 5中使用ObservableCollection的线程安全(并发)版本。由于SL5中缺少多线程支持,我很难找到创建一个版本的方法(没有ReaderWriterLock,没有Collections.Concurrent说话等等)。

我需要该集合在由另一个线程更新时支持UI绑定。当进程在后台运行时,我将所有更新分发到UI线程是不可接受的。理想情况下,后台进程可以根据需要自由更新集合,并且UI会在发生更改时接收通知。这可以通过.NET 4实现,我已经找到了为WPF实现这一目标的方法,但对SL来说却没有。我不能使用WPF示例,因为它们依赖于在SL5中不存在AFAIK的ReaderWriterLock。

赞赏任何方向和/或例子。

更新

在Silverlight中使用(必需)异步通信模式之后,“回调”方法或处理程序在不同的线程上运行。使用TPL(正如我们所做),这是任务的延续。

因为此代码在不同的线程上运行,所以任何影响ObservableCollection的语句都必须编组回UI线程。这意味着流程逻辑和时间现在正在消耗UI线程的资源。

.NET中并发集合的要点是允许生产者和使用者在不同的线程中运行,同时无缝地使用集合中的共享数据。 SL客户端应用程序中的“生产者”将是异步回调或任务延续,“消费者”是绑定到集合的UI。

1 个答案:

答案 0 :(得分:4)

我也反复遇到这个问题,这让我走上你正在看的同一条路。有一个图书馆帮助我完成了这项任务:

http://ch.codeplex.com/

我使用TinyReaderWriterLock实现了我自己的ConcurrentObservableCollection并实现了IList,INotifyCollectionChanged,INotifyPropertyChanged

我以此博客文章为出发点。 http://www.deanchalk.me.uk/post/Thread-Safe-Dispatcher-Safe-Observable-Collection-for-WPF.aspx

在我的版本中,我允许所有调用在调用线程上执行,并且只将INotifyCollectionChanged和INotifyPropertyChanged调用封送回UI线程,如下所示:

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

,其中

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

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

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

这对我来说效果很好。锁定涉及小的性能损失,但对于大多数用途来说并不重要。