Как удалить элементы из списка х секунд после их добавления - PullRequest
2 голосов
/ 27 сентября 2010

Мне нужно удалить элементы из списка через несколько секунд после их добавления. У меня теперь есть ObservableCollection, к которому я добавляю несколько сообщений. Мне нужно, чтобы они были удалены, скажем, через 5 секунд после их добавления. Я попытался создать функцию, отвечающую за добавление элементов и установку таймера:

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();
    }

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

Извините, что раньше не писал. Исключение составляет

этот тип коллекционного представления не поддерживает изменения в своей коллекции источника из потока, отличного от потока диспетчера

Ответы [ 5 ]

1 голос
/ 28 сентября 2010

Вместо удаления элементов из списка по таймеру, почему бы не сохранить время истечения для каждого элемента при его добавлении, а игнорировать или удалять элементы с истекшим сроком действия только тогда, когда вам нужно получить элемент или выполнить итерацию списка?

1 голос
/ 27 сентября 2010

При работе в WPF используйте DispatcherTimer.Я обычно использую что-то вроде этого:

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 будет следить за тем, чтобы событие вызывалось в том же потоке, чтобы вы не столкнулись с проблемами потоков.Другая альтернатива - сделать коллекцию, которую вы привязываете к потоку, безопасной.Но на самом деле, знать, какое исключение вы получили, а не угадывать, было бы проще.

Кроме того, если вы добавляете и удаляете множество элементов в быстрой последовательности или требуете точного выбора времени, вам нужно что-то учитыватьеще;DispatcherTimer не очень точен и несет некоторые накладные расходы, поэтому многие его экземпляры будут потреблять некоторые ресурсы.

0 голосов
/ 28 сентября 2010

Накапливая ответ Брайана выше, вот как вы это делаете через ReactiveXaml ReactiveCollection, расширение ObservableCollection:

theCollection.ItemsAdded
    .Delay(TimeSpan.FromSeconds(5))
    .Subscribe(theCollection.Remove);
0 голосов
/ 27 сентября 2010

Звучит как работа для Реактивные расширения .Вот ссылка на 101 Rx Samples, чтобы показать вам, как начать.

В основном то, что вы хотите сделать (частично псевдокод)

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

Нетнужно иметь дело с таймерами и отсутствием утечек, пока вы избавляетесь от IDisposable, возвращаемого методом Subscribe, когда вы закончите с ним.

Редактировать: Бесстыдная самостоятельная вставка - я сделал сообщение в блоге с примером работающего консольного приложения.Единственное отличие, которое у вас будет, заключается в том, что вы захотите сохранить вызов ObserverOnDispatcher() в своем приложении WPF, или у вас возникнут некоторые ошибки потоков.

0 голосов
/ 27 сентября 2010

убедитесь, что ваш сборщик мусора не избавился от вашего infoList.Попробуйте GC.KeepAlive (infoList)

...