Обновить ObservableCollection с помощью BlockingCollection
Я подписываюсь на сервис, который будет вызывать событие при получении нового элемента, я добавляю этот элемент в BlockingCollection
,
У меня работает второй поток, который будет зацикливать BlockingCollection
добавить / обновить элемент в наблюдаемой коллекции.
Проблема в том, как вы добавляете в ObservableCollection
? Я знаю, я не могу просто сделать .add
на этот тип коллекции, как это должно быть сделано в потоке пользовательского интерфейса. Поэтому я попытался использовать разные ObservableCollection
подкласс, который использует диспетчер, чтобы маршалировать добавление элемента, но каждый раз, я получаю ту же ошибку
"Произошло необработанное исключение типа" System.StackruException "в неизвестном модуле".
с советами по устранению неполадок, как:
убедитесь, что у вас нет бесконечного цикла или бесконечной рекурсии.
Ну, дело в том, что у меня есть какой-то бесконечный цикл на самом деле, как 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 третьей стороны.
2 ответа
Это прекрасный пример того, где Reactive Extensions - очень полезный и оригинальный инструмент. Существует довольно крутая кривая обучения их использованию, но, поскольку у вас есть конкретный пример, я вставлю реактивный код, который достигнет вашей цели, при условии, что я правильно понимаю вашу цель.
Обратите внимание, что вам нужно будет установить Reactive Extensions, и вам понадобятся два оператора using (System.Reactive.Linq и System.Reactive.Subjects), и вам нужно будет ссылаться на dll System.Reactive и System.Reactive.Windows.Threading. См. Реактивный на 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);
}
}
}
В ответе есть небольшая ошибка. Смотрите исправленную строку ниже:
_elementSubscription = _elementSubject.ObserveOnDispatcher().Subscribe(NextElement);
Мне потребовалось некоторое время, чтобы понять это, но ответ rmayer06 решил мою проблему. Я не могу комментировать ответы, или я бы получил.