2013-07-10 1 views
0

У меня есть случай использования, в котором я хочу вставить и удалить пользовательский объект (запасы) из блокирующей коллекции (более крупное изображение представляет собой очередь производителей-потребителей).Удаление элементов из BlockingCollection и заполнение Наблюдаемая коллекция

Проблемы утверждение точно похож на эту тему - update an ObservableCollection with a BlockingCollection

Я не хочу использовать реактивные расширения, но хочу традиционный C# способа сделать эту логику (это жесткое требование, к сожалению, и полностью понять последствие). Мой фрагмент кода здесь

MainWindowViewModel.cs

public class MainWindow_VM : ViewModelBase 
{ 
    public ObservableCollection<StockModel> stocks { get; set; } 
    private readonly Dispatcher currentDispatcher; 
    private BlockingCollection<StockModel> tasks = new BlockingCollection<StockModel>(); 
    #endregion 

// All other standard ViewModel logic - Constructor, Command etc 

    private void handlermethod(object sender, MarketDataEventArgs e) 
    { 
     Task.Factory.StartNew(AddUpdateObservableCollection); 

     // Below thought process (maybe wrong) - How do i add the value to the BlockingCollection through a thread considering I have a ProducerConsumer class standard implementation (which has Enqueue and Dequeue Methods) 
     using (ProducerConsumerQueue q = new ProducerConsumerQueue()) 
     { 
       foreach (Stock s in e.updatedstock) 
       { 
        StockModel sm = new StockModel(); 
        sm.Symbol = s.Symbol; 
        sm.Bidprice = s.Bidprice; 

        q.EnqueueTask(s); 
       } 
    } 

    private void AddUpdateObservableCollection() 
    { 
     //Signalling mechanism still missing - when Stock comes into BlockingCollection - then this will start draining. 
     // Also have to take care of Dispatcher stuff since you can only update ObservableCollection through Dispatcher 

     foreach (StockModel sm in tasks) 
     { 
      if (sm != null) 
      { 
       if (stocks.Any(x => x.Symbol == sm.Symbol)) 
       { 
        var found = stocks.FirstOrDefault(x => x.Symbol == sm.Symbol); 
        int i = stocks.IndexOf(found); 
        stocks[i] = sm; 
       } 
       else 
       { 
        stocks.Add(sm); 
       } 
      } 
     } 
    } 
} 
+0

Вы добавляете и снимаете с BlockingCollection. – Paparazzi

ответ

2

Похоже, проблема в том, что ваш метод AddUpdateObservableCollection видит, что tasks коллекция пуста, а затем завершает свою работу.

Если вы хотите, чтобы быть стойкими, замените ваш foreach с:

foreach (StockModel sm in tasks.GetConsumingEnumerable()) 

Перечислитель вы получите от GetConsumingEnumerable заблокирует ожидание пунктов, которые будут добавлены в очередь, и будет продолжать блокировать, пока другой thread замечает коллекцию как полную для добавления. Поэтому, когда вы закончите добавлять вещи в очередь и хотите, чтобы метод AddUpdateObservableCollection вышел, просто позвоните tasks.CompleteAdding(). Цикл будет опущен в очередь, см., Что больше не ожидается новых элементов (потому что свойство IsAddingCompleted - true) и выход.

Я немного запутался в том, как вы получаете вещи в блокирующую коллекцию. Ваш фрагмент кода не слишком ясен. Если у вас возникли проблемы с этим, отредактируйте свой вопрос и объясните, в чем проблема. Комментарий в коде для handlermethod довольно загадочный.

+0

Спасибо Джим. Я использую Pub/Sub, чтобы получить данные в моем обработчике. См. Диаграмму, которую я разместил здесь - http://stackoverflow.com/questions/17451531/real-time-data-binding – Patrick

Смежные вопросы