Удаление элементов из BlockingCollection и заполнение Observable Collection

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

Постановка задачи в точности аналогична этой теме - обновите ObservableCollection с 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);
                }
            }
        }
    }
}

1 ответ

Решение

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

Если вы хотите, чтобы он был постоянным, замените foreach с:

foreach (StockModel sm in tasks.GetConsumingEnumerable())

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

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

Другие вопросы по тегам