Одна из вещей, которые долгое время беспокоили меня о FileSystemWatcher, - это способ, которым он запускает несколько событий для одного логического изменения файла. Я знаю, почему это происходит, но я не хочу заботиться - я просто хочу повторно просмотреть файл один раз, а не 4-6 раз подряд. В идеале, произойдет событие, которое срабатывает только тогда, когда заданный файл будет изменен, а не каждый шаг на этом пути.
На протяжении многих лет я придумывал различные решения этой проблемы, различной степени уродства. Я думал, что Reactive Extensions станет окончательным решением, но там что-то я не делаю правильно, и я надеюсь, что кто-то может указать на мою ошибку.
У меня есть метод расширения:
public static IObservable<IEvent<FileSystemEventArgs>> GetChanged(this FileSystemWatcher that)
{
return Observable.FromEvent<FileSystemEventArgs>(that, "Changed");
}
В конечном счете, я хотел бы получить одно событие за имя файла за определенный период времени, чтобы четыре события в строке с одним именем файла были сведены к одному событию, но я ничего не теряю, если несколько файлов изменены в то же время. BufferWithTime
звучит как идеальное решение.
var bufferedChange = watcher.GetChanged()
.Select(e => e.EventArgs.FullPath)
.BufferWithTime(TimeSpan.FromSeconds(1))
.Where(e => e.Count > 0)
.Select(e => e.Distinct());
Когда я подписываюсь на это наблюдаемое, одно изменение в контролируемом файле трижды запускает мой метод подписки, что скорее поражает цель. Если я удалю вызов Distinct()
, я вижу, что каждый из четырех вызовов содержит два одинаковых события, поэтому происходит буферизация. Увеличение TimeSpan, переданное на BufferWithTime
, похоже, не имеет эффекта - я прошел до 20 секунд без каких-либо изменений в поведении.
Это мой первый набег на Rx, поэтому я, вероятно, пропустил что-то очевидное. Я делаю это неправильно? Есть ли лучший подход? Спасибо за любые предложения...