2013-07-10 3 views
0

J'ai un cas d'utilisation dans lequel je souhaite insérer et supprimer un objet personnalisé (Stocks) d'une collection de blocage (image plus grande représentant une file d'attente de producteur).Suppression d'éléments de BlockingCollection et remplissage de la collection observable

L'énoncé du problème est exactement semblable à ce fil - update an ObservableCollection with a BlockingCollection

Je ne veux pas utiliser des extensions réactives mais veulent une manière traditionnelle C# pour faire cette logique (ce qui est une exigence difficile à comprendre, malheureusement, et complètement les implications). Mon bout de code est ici

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

Vous ajoutez et prenez à partir d'un BlockingCollection. – Paparazzi

Répondre

2

Il semble que le problème est que votre méthode AddUpdateObservableCollection voit que la collection tasks est vide, puis sort.

Si vous voulez qu'il soit persistant, remplacer votre foreach avec:

foreach (StockModel sm in tasks.GetConsumingEnumerable()) 

Le recenseur que vous obtenez de GetConsumingEnumerable bloquera en attente sur les éléments à ajouter à la file d'attente, et continuera à bloquer jusqu'à ce que l'autre thread marque la collection comme complète pour l'ajout. Ainsi, lorsque vous avez terminé d'ajouter des éléments à la file d'attente et que vous souhaitez quitter la méthode AddUpdateObservableCollection, appelez simplement tasks.CompleteAdding(). La boucle va vider la file d'attente, voir que plus d'éléments sont à venir (parce que la propriété IsAddingCompleted est true), et quittez. Mais je suis un peu confus quant à la façon dont vous obtenez des choses dans la collection de blocage, cependant. Votre extrait de code n'est pas trop clair. Si vous rencontrez des problèmes, modifiez votre question et expliquez le problème. Le commentaire dans le code pour handlermethod est assez cryptique.

+0

Merci Jim. J'utilise un Pub/Sub pour obtenir les données dans mon gestionnaire. S'il vous plaît voir le diagramme que j'ai posté ici - http://stackoverflow.com/questions/17451531/real-time-data-binding – Patrick

Questions connexes