using System; using System.IO; using System.Runtime.Caching; namespace wasSharpNET.IO { /// /// Filesystem watcher that ensures events are not fired twice /// /// derived from Ben Hall @ benhall.io public class FileSystemWatcher : IDisposable { public event FileSystemEventHandler FilesytemEvent; private readonly CacheItemPolicy _cacheItemPolicy; private readonly int _cacheTimeMilliseconds = 1000; private readonly MemoryCache _memCache; public FileSystemWatcher(string path, NotifyFilters notifyFilters, string filter) { _memCache = MemoryCache.Default; var watcher = new System.IO.FileSystemWatcher { Path = path, NotifyFilter = notifyFilters, Filter = filter }; _cacheItemPolicy = new CacheItemPolicy { RemovedCallback = OnRemovedFromCache }; watcher.Changed += OnChanged; watcher.EnableRaisingEvents = true; } public FileSystemWatcher(string path, NotifyFilters notifyFilters, string filter, int timeout) : this(path, notifyFilters, filter) { _cacheTimeMilliseconds = timeout; } // Add file event to cache for CacheTimeMilliseconds private void OnChanged(object source, FileSystemEventArgs e) { _cacheItemPolicy.AbsoluteExpiration = DateTimeOffset.Now.AddMilliseconds(_cacheTimeMilliseconds); // Only add if it is not there already (swallow others) _memCache.AddOrGetExisting(e.Name, e, _cacheItemPolicy); } // Handle cache item expiring private void OnRemovedFromCache(CacheEntryRemovedArguments args) { if (args.RemovedReason != CacheEntryRemovedReason.Expired) return; // Now actually handle file event. OnFileSystemEvent((FileSystemEventArgs)args.CacheItem.Value); } protected virtual void OnFileSystemEvent(FileSystemEventArgs e) { FilesytemEvent?.Invoke(this, e); } public void Dispose() { _memCache.Dispose(); } } }