FileSystemWatcher Changed event is raised twice

前端 未结 30 3307
死守一世寂寞
死守一世寂寞 2020-11-22 06:01

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

30条回答
  •  难免孤独
    2020-11-22 06:26

    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)
    

提交回复
热议问题