我订阅了一项服务,该服务将在收到新元素时引发Event,然后将此元素添加到BlockingCollection中。
我有第二个线程正在运行,它将循环BlockingCollection以添加/更新可观察集合中的元素。

问题是如何添加ObservableCollection
我知道我不能只对这种类型的集合执行.add,因为它需要在UI线程上完成。所以我尝试使用不同的ObservableCollection子类,该子类使用分派(dispatch)器来编码元素的添加,但是每一次,我都会遇到相同的错误



具有以下故障排除提示:



好吧,实际上,我确实有某种无限循环,因为BlockingQueue一直在接收新元素,例如每秒5到10。
如果我不将控件绑定(bind)到observablecollection,或者我使用List代替,则不会出现异常。

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);
            }
        }
    }

编辑
当我进行跟踪时,该错误本身就消失了。我试图使事情变得更简单,以真正了解问题所在,然后开始起作用。当将所有内容放回原处时,它仍然可以正常工作……但是有时会不时地返回,原因似乎不相关,例如在我的 ListView 中添加样式。我开始认为第三方dll中存在问题。

最佳答案

这是一个很好的例子,其中Reactive Extensions是一个非常有用且精巧的工具。使用它们的学习曲线非常陡峭,但是由于您在这里有一个特定的案例,因此,假设我正确理解了您的目标,我将插入能够实现您的目标的响应式(Reactive)代码。

请注意,您将需要安装Reactive Extensions,并且将需要两个using语句(System.Reactive.Linq和System.Reactive.Subjects),并且将需要引用System.Reactive和System.Reactive.Windows.Threading dll。参见Reactive on 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);
        }
    }
}

关于c# - 使用BlockingCollection更新ObservableCollection,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13234103/

10-09 01:18
查看更多