I have an application where I am looking for a text file and if there are any changes made to the file I am using the OnChanged
eventhandler to handle the event
mostly for future me :)
I wrote a wrapper using Rx:
public class WatcherWrapper : IDisposable
{
private readonly FileSystemWatcher _fileWatcher;
private readonly Subject _infoSubject;
private Subject _eventSubject;
public WatcherWrapper(string path, string nameFilter = "*.*", NotifyFilters? notifyFilters = null)
{
_fileWatcher = new FileSystemWatcher(path, nameFilter);
if (notifyFilters != null)
{
_fileWatcher.NotifyFilter = notifyFilters.Value;
}
_infoSubject = new Subject();
_eventSubject = new Subject();
Observable.FromEventPattern(_fileWatcher, "Changed").Select(e => e.EventArgs)
.Subscribe(_infoSubject.OnNext);
Observable.FromEventPattern(_fileWatcher, "Created").Select(e => e.EventArgs)
.Subscribe(_infoSubject.OnNext);
Observable.FromEventPattern(_fileWatcher, "Deleted").Select(e => e.EventArgs)
.Subscribe(_infoSubject.OnNext);
Observable.FromEventPattern(_fileWatcher, "Renamed").Select(e => e.EventArgs)
.Subscribe(_infoSubject.OnNext);
// this takes care of double events and still works with changing the name of the same file after a while
_infoSubject.Buffer(TimeSpan.FromMilliseconds(20))
.Select(x => x.GroupBy(z => z.FullPath).Select(z => z.LastOrDefault()).Subscribe(
infos =>
{
if (infos != null)
foreach (var info in infos)
{
{
_eventSubject.OnNext(info);
}
}
});
_fileWatcher.EnableRaisingEvents = true;
}
public IObservable FileEvents => _eventSubject;
public void Dispose()
{
_fileWatcher?.Dispose();
_eventSubject.Dispose();
_infoSubject.Dispose();
}
}
Usage:
var watcher = new WatcherWrapper(_path, "*.info");
// all more complicated and scenario specific filtering of events can be done here
watcher.FileEvents.Where(x => x.ChangeType != WatcherChangeTypes.Deleted).Subscribe(x => //do stuff)