3

I'm looking for a replacement for ObservableCollection that is thread-safe, raises events on the UI thread and preferably has an AddRange method. I've seen a few implementations posted here and elsewhere, but I'd prefer an implementation that has been tested and validated and that I won't have to maintain myself.

So can anyone point me to such a replacement, preferable available via NuGet?

HolySamosa
  • 9,011
  • 14
  • 69
  • 102
  • 2
    `ObservableCollection` is used for Data Binding. Data Binding is almost always in a User-Interface context. Do you mean an observable collection that raises events within a specific synchronization context (e.g. the UI thread)? Or do you mean an observable collection that uses an internal collection type that is thread-safe? (or both?) – Peter Ritchie Sep 17 '12 at 21:58
  • Thanks, Peter. Both, I think. I need to raise events on the UI thread to support WPF data binding, however collection modifications will be made by non-UI threads. – HolySamosa Sep 17 '12 at 22:33
  • It's fairly typical that `ObservableCollection` event handlers deal with whatever thread synchronization implementation details they need (e.g. two event handlers could have different thread synchronization requirements. For a class to raise an event on the correct thread in this case would require more information than just an event subscription). As for thread-safe writes to `ObservableCollection`--it's not a common scenario; but when it is, simply *use* of the collection is generally locked... – Peter Ritchie Sep 17 '12 at 23:00
  • ...it's impossible for a particular class to be thread-safe for everyone else. They can only be thread-safe within themselves. e.g. what does it mean to be "thread safe" enumerating a collection? – Peter Ritchie Sep 17 '12 at 23:02
  • Try the following link which provides a thread-safe solution that works from any thread and can be bound to via multiple UI threads : http://www.codeproject.com/Articles/64936/Multithreaded-ObservableImmutableCollection – Anthony Apr 15 '14 at 19:20

3 Answers3

3

For thread safe collections check the System.Collections.Concurrent namespace. ConcurrentStack has a PushRange method that inserts multiple objects at the top of the stack.

t.olev
  • 73
  • 5
  • Thanks, T., but I specifically need an implementation of ObservableCollection (which raises events when the collection changes). Unfortunately this isn't included in .NET's concurrent implementations. – HolySamosa Sep 17 '12 at 21:50
  • 1
    @HolySamosa: Although the `ConcurrentStack` is not 'observable', you can make it so very easily by implementing `INotifyPropertyChaqnged` or a similar interface. – IAbstract Sep 17 '12 at 22:03
  • @IAbstract You can't, the methods of `ConcurrentStack` that would need to be overridden aren't virtual. –  Sep 17 '12 at 22:11
  • I think you won't need to override them, you just have to subclass ConcurrentStack and with the subclass to implement INotifyPropertyChanged and then you can use all the methods of ConcurrentStack and to notify the observers on property change. – t.olev Sep 18 '12 at 06:55
  • @t.olev `INotifyCollectionChanged`, not `INotifyPropertyChanged`. Your code doesn't get executed at all when for example `((ConcurrentStack)stack).Clear()` is called, so how would the required events get fired? Sure, you can implement `INotifyCollectionChanged`, allow others to subscribe to your event, and then not raise that event, but that won't help anyone. –  Sep 18 '12 at 08:02
  • OK ObservableCollection according to MSDN is this thing exactly: public class ObservableCollection : Collection, INotifyCollectionChanged, NotifyPropertyChanged So what is the problem with implementing something like this : public MyStack : ConcurrentStack, INotifyCollectionChanged, INotifyPropertyChanged – t.olev Sep 18 '12 at 08:56
  • @t.olev Indeed, `INotifyPropertyChanged` is also implemented by `ObservableCollection`, that's just not the interface that matters here. Sorry if I was unclear about that. –  Sep 18 '12 at 08:58
  • @t.olev I didn't see your edit before, but "So what is the problem with implementing something like this : `public MyStack : ConcurrentStack, INotifyCollectionChanged, INotifyPropertyChanged`" -- again, the fact that it's not possible to implement `INotifyCollectionChanged` correctly. If you doubt that, I welcome you to try it yourself, and I'll be glad to provide a counterexample that doesn't work with your implementation. :) –  Sep 18 '12 at 09:37
  • @hvd, I tried it (although there was no need after carefully thinking) - you're right, it is not possible to subclass `ConcurrentStack` and implement `INotifyCollectionChanged` and make this work correctly... Sorry for getting confused earlier, it still is some approach for substituting `ObservableCollection` with another thread safe collection but it won't work properly with methods for adding or removing a set of items in/from the collection. Maybe better approach for @HolySamosa is to use `ObservableCollection` with additional method that will help operating with a range of items. – t.olev Sep 18 '12 at 20:31
  • As `ObservableCollection` implements `IList`, and `IList` is by design not thread-safe, that won't be workable either. Callers that add an item to a `ICollection`, from which `IList` derives, are guaranteed that after `Add` returns, the list's count has not decreased. Another simpler example, `IList` must allow for a `for (int i = 0; i != list.Count; i++) { Process(list[i]); }` loops. The non-generic `ICollection`/`IList` interfaces have an `IsSynchronized` property that thread-safe collections can make return `true`, but `IList` by design cannot do that. –  Sep 18 '12 at 20:39
  • 1
    Depending on what the reason for the question is, it may be easier to use an unmodified `ObservableCollection`, and post messages to the synchronization context to add/remove items from it (depending on what you do, you can fire off the message and not wait for it), rather than having the background thread do that directly. –  Sep 18 '12 at 20:40
2

You could try using the BulkObservableCollection from Microsoft, although I'm not sure why they put it in such a strange namespace! Didn't see it listed when I tried to "Add reference..." in VS2012, had to manually browse to C:\Windows\Microsoft.NET\assembly\GAC_MSIL

lanternmarsh
  • 683
  • 6
  • 8
  • Given that this class is in the VisualStudio namespace, and not part of the core framework, it seems likely that there may be re-distribution issues for anything other than in-house applications. – paytools-steve Mar 13 '14 at 21:27
  • @lanternmarsh WHY is this thing hidden? its way better than crappy ObservableCollection – Aaron. S Dec 04 '19 at 07:08
0

You can try the one described here:

http://deanchalk.com/2010/02/01/thread-safe-dispatcher-safe-observable-collection-for-wpf/

It is a full implementation in a blog post. It is available as source (from that page), so it might not meet your tested/validated criteria.

I have not used it, so I cannot vouch for how well it works (or doesn't).

UPDATE: The old link was broken. I replaced it with the current link. The Dean Chalk is actually a member here on SO, so here is a link to his SO profile in case it ever breaks again:

https://stackoverflow.com/users/328848/dean-chalk

Community
  • 1
  • 1
wageoghe
  • 27,390
  • 13
  • 88
  • 116