我订阅了一项服务,当收到新元素时,该服务将引发一个事件,我将此元素添加到BlockingCollection
.
我有第二个线程正在运行,它将循环BlockingCollection
添加/更新可观察集合中的元素。
问题是你如何添加ObservableCollection
?
我知道我不能只是做一个.add
对于这种类型的集合,因为它需要在 UI 线程上完成。所以我尝试使用不同的ObservableCollection
使用调度程序来编组元素添加的子类,但每次我都会遇到相同的错误
“‘System.StackOverflowException’类型的未处理异常
发生在未知模块中。”
故障排除提示如下:
确保没有无限循环或无限递归。
事实是,我实际上确实有某种无限循环,因为BlockingQueue
一直在接收新元素,比如每秒 5 到 10 个。
如果我不将控件绑定到,我不会得到异常observablecollection
不过,或者如果我使用列表代替。
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);
}
}
}
编辑
当我追踪它时,该错误自行消失了。我试图让事情变得更简单,以真正理解问题所在,然后它开始起作用。当把东西重新组合在一起时,它仍然有效......但它会时不时地回来,因为似乎不相关的原因,比如向我的列表视图添加样式。我开始认为第三方 dll 存在问题。
这是一个完美的例子,说明反应式扩展是一个非常有用和巧妙的工具。使用它们有一个相当陡峭的学习曲线,但由于您在这里有一个特定的案例,假设我正确理解您的目标,我将插入将实现您的目标的反应式代码。
请注意,您将需要安装 Reactive Extensions,并且需要两个 using 语句(System.Reactive.Linq 和 System.Reactive.Subjects),并且需要引用 System.Reactive 和 System.Reactive.Windows.Threading dll。看MSDN 上的响应式 http://msdn.microsoft.com/en-us/data/gg577609.aspx.
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);
}
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)