3

我需要Silverlight 5中的ObservableCollection的線程安全(併發)版本。由於SL5中缺少多線程支持,我正在努力尋找一種方法來創建一個(無ReaderWriterLock,no集合,同時說話等)。Silverlight中的併發ObservableCollection 5

我需要集合來支持UI綁定,同時被另一個線程更新。當進程在後臺運行時,我無法將所有更新都分發到UI線程。理想情況下,後臺進程可根據需要自由更新集合,並且UI在發生更改時接收通知。這對.NET 4來說是可能的,我已經找到了爲WPF完成這個任務的方法,但是沒有爲SL做過任何事情。我無法使用WPF示例,因爲它們依賴於ReaderWriterLock,AFAIK不在SL5中。

讚賞任何方向和/或例子。

UPDATE

繼在Silverlight中,「回調」的方法,或處理程序使用的異步通信模式(必需),運行在不同的線程。使用TPL(和我們一樣),這是任務的延續。

由於此代碼在不同的線程上運行,因此任何影響ObservableCollection的語句都必須編組回UI線程。這意味着流程邏輯和時間正在消耗UI線程的資源。

.NET中的併發集合的要點是允許生產者和消費者運行在不同的線程中,但可以無縫地處理集合中的共享數據。 SL客戶端應用程序中的「生產者」將是異步回調或任務延續,「消費者」是綁定到集合的UI。

+0

我以爲綁定'ObservableCollection'需要在UI線程上更新,否則你會得到異常。所以,沒有鎖定機制會幫助你。 – svick 2012-03-07 21:38:20

+0

是和不是。 ObservableCollection需要在UI線程上更新的原因是因爲必須在UI線程上觸發PropertyChanged和CollectionChanged事件。如果它們不是,UI將不會按預期處理它們。 ObservableCollection中沒有什麼阻礙其他線程的更改,它不會更新綁定,這是使用該集合的全部要點。某種類型的併發機制允許生產者在引發UI線程上的事件的同時更改不同線程上的集合,這是我們所需要的。 – SonOfPirate 2012-03-08 01:18:24

+0

這和第一個改變UI線程的集合有什麼不同?我的意思是,那有什麼好處呢? – svick 2012-03-08 01:28:58

回答

4

我也反覆碰到這個問題,這使我走下了同樣的道路,你看着。目前已經幫助了我極大的這個任務庫:

http://ch.codeplex.com/

我實現了使用TinyReaderWriterLock和實施的IList,INotifyCollectionChanged我自己ConcurrentObservableCollection,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); 
    } 
} 

這對我來說效果很好。鎖定涉及性能不佳,但對於大多數用途來說並不重要。

+0

非常好!正是我在找什麼。 – SonOfPirate 2012-03-23 00:11:35

+0

你能詳細解釋一下你的解決方案嗎?該博客的鏈接不再有效。我很難實現這個ConcurrentObservableCollection。 – Peter 2013-02-09 10:46:19