Update ObservableCollection with BlockingCollection

I subscribe to a service that will raise an event when a new item is received, I will add this item to the BlockingCollection .
I have a second thread that will run BlockingCollection to add / update an item in the observed collection.

The problem is how you add to the ObservableCollection ? I know that I cannot just do .add in this type of collection, as this needs to be done in the user interface thread. So I tried to use another subclass of ObservableCollection , which the dispatcher uses to marshal the addition of an element, but every time I get the same error

"An unhandled exception of type 'System.StackOverflowException' occurred in the Unknown module.

with troubleshooting tips:

make sure you don't have an infinite loop or inifiniterecursion.

Well, the fact is that I actually have some kind of infinite loop, since BlockingQueue gets new elements all the time, for example 5-10 per second.
I will not get an exception unless I bind the control to an ObservableCollection , though if I use the List instead.

 Class ElementHolder { private ExternalService _externalService; private ObservableCollection<Element> _elementsList = new ObservableCollection<Element>(); private BlockingCollection<Element> _elementsReceived = new BlockingCollection<Element>(); public ObservableCollection<Element> ElementsList { get { return _elementList; } set { _elementList = value; } } public ElementHolder() { Task.Factory.StartNew(ReadElements); _externalService = new ExternalService(); _externalService.ReceivedNewElement += new Action<Element>(o => _elementsReceived.Add(o)); _externalService.Subscribe(); } private void ReadElements() { foreach (Element element in _elementsReceived.GetConsumingEnumerable()) { Element item = _elementsList.FirstOrDefault(o => o.ID == element.ID); if (item == null) { _elementList.Add(element); } else { item.Update(element); } } } 

EDIT The error disappeared on its own when I tracked it. I tried to make things easier to figure out where the problem is, and then it started working. When everything comes together, it still works ... BUT it comes back from time to time because it seems unrelated to something like adding a style to my list. I'm starting to think that there is a problem in a third-party DLL.

+4
source share
2 answers

This is a great example of where Reactive Extensions is a very useful and inventive tool. There is a pretty steep learning curve to use them, but since you have a specific case, I will insert a reactive code that will achieve your goal if I understand your goal correctly.

Note that you will need to install Reactive Extensions, and you will need two using statements (System.Reactive.Linq and System.Reactive.Subjects), and you will need to reference System.Reactive and System.Reactive.Windows. Threading dlls. See "Responding to MSDN . "

 class ElementHolder { public ObservableCollection<Element> ElementsList { get; set; } private ExternalService _externalService = new ExternalService(); private IDisposable _elementSubscription; private Subject<Element> _elementSubject = new Subject<Element>(); public ElementHolder() { _externalService.ReceivedNewElement += _elementSubject.OnNext; _externalService.Subscribe(); ElementList = new ObservableCollection<Element>(); _elementSubscription = _externalService.ObserveOnDispatcher().Subscribe(NextElement); } private void NextElement(Element e) { Element item = ElementsList.FirstOrDefault(o => o.ID == element.ID); if (item == null) { _elementList.Add(element); } else { item.Update(element); } } } 
+3
source

There is a small error in the answer. See the corrected line below:

 _elementSubscription = _elementSubject.ObserveOnDispatcher().Subscribe(NextElement); 

It took me a while to figure this out, but rmayer06's answer solved my problem. I can not comment on the answers or I would like.

0
source

Source: https://habr.com/ru/post/1444131/


All Articles