在Silverlight 5中,我需要一个线程安全(并发)版本的ObservableCollection。考虑到SL5中缺乏多线程支持,我很难找到一种方法来创建它(没有ReaderWriterLock,也没有Collections.Concurrent,等等)。
当被另一个线程更新时,我需要集合来支持UI绑定。当进程在后台运行时,我无法将所有更新分派到UI线程。理想情况下,后台进程可以根据需要更新集合,并且UI在发生更改时接收通知。这在.NET 4中是可能的,我已经为WPF找到了实现这一目标的方法,而SL却没有。我不能使用WPF示例,因为它们依赖于ReaderWriterLock,AFAIK在SL5中不存在。
任何方向和/或实例都将受到赞赏。
更新
按照Silverlight中使用的异步通信模式(必需),“回调”方法或处理程序在不同的线程上运行。使用TPL (就像我们所做的),这是任务的延续。
因为这段代码运行在不同的线程上,所以任何影响ObservableCollection的语句都必须被封送回UI线程。这意味着进程逻辑和时间现在正在消耗UI线程的资源。
.NET中并发集合的目的是允许生产者和使用者在不同的线程中运行,但是可以无缝地处理集合中的共享数据。SL客户端应用程序中的“生产者”将是异步回调或任务延续,“使用者”是绑定到集合的UI。
发布于 2012-03-22 17:34:00
我也多次遇到这个问题,这使我走上了你所看到的同一条路。有一个图书馆帮了我很大的忙:
http://ch.codeplex.com/
我使用TinyReaderWriterLock实现了自己的TinyReaderWriterLock,并实现了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);
}
}这对我来说很管用。锁定对性能的影响很小,但在大多数情况下并不显着。
https://stackoverflow.com/questions/9609009
复制相似问题