使用BlockingCollection更新ObservableCollection

我订阅了一个服务,当收到一个新元素时会引发一个事件,我将这个元素添加到一个BlockingCollection
我有第二个线程运行,它将循环BlockingCollection以在可观察集合中添加/更新元素。

问题是你如何添加ObservableCollection ? 我知道我不能在这种类型的集合上做一个.add ,因为它需要在UI线程上完成。 所以我尝试使用不同的ObservableCollection子类,它使用调度程序来编组元素的添加,但每次都会出现同样的错误

“Unknown Module中发生了’System.StackOverflowException’类型的未处理exception。”

有一个疑难解答提示:

确保你没有无限循环或无限递归。

嗯,实际上,我确实有一些无限循环,因为BlockingQueue一直在接收新的元素,比如每秒5到10个。
如果我没有将控件绑定到observablecollection ,或者如果我使用List,那么我不会得到exception。

 Class ElementHolder { private ExternalService _externalService; private ObservableCollection _elementsList = new ObservableCollection(); private BlockingCollection _elementsReceived = new BlockingCollection(); public ObservableCollection ElementsList { get { return _elementList; } set { _elementList = value; } } public ElementHolder() { Task.Factory.StartNew(ReadElements); _externalService = new ExternalService(); _externalService.ReceivedNewElement += new Action(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); } } } 

编辑当我跟踪它时,错误自行消失。 我试图让事情变得更简单,以便真正了解问题所在,然后开始发挥作用。 当把东西放回去时它仍然可以工作……但它不时地回来,因为似乎无关的原因就像在我的列表视图中添加一个样式。 我开始认为第三方dll存在问题。

这是Reactive Extensions是一个非常有用和巧妙的工具的完美示例。 使用它们有一个相当陡峭的学习曲线,但由于你在这里有一个特定的案例,我将插入将实现你的目标的反应代码,假设我正确理解你的目标。

请注意,您需要安装Reactive Extensions,并且需要两个using语句(System.Reactive.Linq和System.Reactive.Subjects),您需要引用System.Reactive和System.Reactive.Windows.Threading dll。 请参阅MSDN上的Reactive 。

 class ElementHolder { public ObservableCollection ElementsList { get; set; } private ExternalService _externalService = new ExternalService(); private IDisposable _elementSubscription; private Subject _elementSubject = new Subject(); public ElementHolder() { _externalService.ReceivedNewElement += _elementSubject.OnNext; _externalService.Subscribe(); ElementList = new ObservableCollection(); _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); } } } 

答案中有一个小错误。 请参阅下面的更正行:

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

我花了一段时间来解决这个问题,但是rmayer06的答案解决了我的问题。 我不能评论答案,或者我会。