2010-09-27 6 views
2

Je dois supprimer des éléments de la liste quelques secondes après les avoir ajoutés. J'ai maintenant une ObservableCollection à laquelle j'ajoute quelques messages. J'ai besoin qu'ils soient supprimés, disons 5 secondes après leur ajout. J'ai essayé de créer une fonction responsable de l'ajout des éléments et définir une minuterie:Comment supprimer des éléments de la liste x secondes après les avoir ajoutés

public void AddInfoItem(string info) 
    { 
     infoList.Add(info); 
     Timer newTimer = new Timer(5000); 
     newTimer.Elapsed += new ElapsedEventHandler(this.TimerFunction); 
     newTimer.Enabled = true; 
     newTimer.Start(); 
    } 
public void TimerFunction(Object sender, EventArgs e) 
    { 
     infoList.Clear(); 
    } 

Je ne savais même envoyer des paramètres quel élément doit être retiré cause de la deuxième fonction a soulevé une exception. Quelqu'un peut-il décrire une solution appropriée pour ajouter un élément et le supprimer après un certain temps?

Sory pour ne pas l'avoir écrit plus tôt. L'exception est

ce type de CollectionView ne supporte pas les changements à son sourcecollection d'un fil différent du fil dispatecher

+2

Quelle était l'exception? – Val

+0

Comme Val a dit - quelle est l'exception? –

Répondre

1

Si vous travaillez dans WPF, utilisez DispatcherTimer. Je l'habitude d'utiliser quelque chose comme ceci:

public static void Delay(int milliseconds, Action action) 
{ 
    var t = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(milliseconds) }; 
    t.Tick += (o, e) => { t.Stop(); action.Invoke(); }; 
    t.Start(); 
} 

DispatcherTimer fera en sorte que l'événement est invoqué sur le même thread afin de ne pas en problèmes de filetage. Une autre alternative consiste à rendre la collection que vous liez au thread sécurisé. Mais en effet, savoir quel genre d'exception vous avez reçu au lieu de deviner serait plus facile. En outre, si vous ajoutez et enlevez rapidement un grand nombre d'éléments ou si vous souhaitez que votre timing soit précis, vous devez envisager autre chose; DispatcherTimer n'est pas très précis et supporte certains frais généraux, donc beaucoup d'instances consommeront des ressources.

-2

Assurez-vous que votre garbage collector ne disposait pas de votre infolist. Essayez GC.KeepAlive (infoList)

+1

Semble peu probable d'être la cause ... Puisque infoList est défini (et donc référencé) quelque part en dehors de la méthode, il semble peu probable que le GC en soit la cause.Vous devriez définir 'infoList = null' pour GC pour le nettoyer, et cela donnerait une' NullReferenceException' (qui, espérons-le, n'aurait pas besoin d'une question SO à résoudre ...). –

+0

GC.KeepAlive ne fait rien. Vous pouvez l'implémenter comme ceci: void Foo (object bar) {} '. Ce n'est utile que lorsque vous n'avez aucune référence à un objet utilisé hors de portée du garbage collector, comme du code non géré. –

0

Cela ressemble à un travail pour Reactive Extensions. Voici a link à 101 échantillons Rx pour vous montrer comment y aller.

Fondamentalement, ce que vous voulez faire (partie du code pseudo)

Observable 
.FromEvent<NotifyCollectionChangedEventArgs>(infoList, "CollectionChanged") 
.Where(args => args.Action == NotifyCollectionChangedAction.Add) 
.Delay(TimeSpan.FromSeconds(5)) 
.ObserveOnDispatcher() 
.Subscribe(args => infoList.Remove(args.NewItems)); 

Pas besoin de traiter les minuteries et pas de fuite aussi longtemps que vous disposez du IDisposable retourné par la méthode Abonnez-vous lorsque vous » re fait avec.

Edit: Shameless plug auto - Je l'ai fait un blog post avec un exemple d'application de la console de travail. La seule différence que vous aurez est que vous voulez garder l'appel ObserverOnDispatcher() dans votre application WPF ou vous obtiendrez des erreurs de thread.

+0

Bien que cela fonctionne très bien lorsque vous utilisez déjà beaucoup d'extensions réactives dans l'application, il semble que ce soit trop compliqué pour un problème simple. – ForbesLindesay

+0

@ Tuskan360 Une fois que vous commencez à utiliser Rx, vous verrez beaucoup d'endroits où vous pouvez écrire un code beaucoup plus simple que ce que vous avez déjà en place. Le premier coup est libre comme on dit. –

0

Empiler sur la réponse de Bryan ci-dessus, voici comment vous le faites via ReactiveCollection de ReactiveXaml, une extension de ObservableCollection:

theCollection.ItemsAdded 
    .Delay(TimeSpan.FromSeconds(5)) 
    .Subscribe(theCollection.Remove); 
+0

Cela ressemble à une bibliothèque vraiment cool! Je l'ajoute définitivement à ma liste de projets à suivre. –

1

plutôt de supprimer des éléments de la liste sur une minuterie, pourquoi ne pas stocker une heure d'expiration avec chaque élément lorsqu'il est ajouté, et ignore ou supprime les éléments expirés uniquement lorsque vous devez récupérer un élément ou itérer la liste?

Questions connexes