C# FileSystemWatcher 组件应用
在ScheduledJob专案中,要用到很多自定义的DLL组件,为了保证运行的效能,我们采用“缓存”的方式对这些组件进行事先加载,待应用时在内存中既可找到对应的组件并运行,而无需每次都Load. 而这些组件随时都可能有异动,可能新增,可能修改,此时要保证缓存的内容也及时更新,就必须采取一种机制保证,这些组件表更时,能同时更新到内存缓存中。
在C#中我们可以采用FileSystemWatcher组件实现。
using System; using System.Collections.Generic; using System.IO; namespace fileSystemWatcherDemo { /// <summary> /// FileSystemWatcher 组件应用Demo 1 /// </summary> class fileSystemWatcherDemo { private FileSystemWatcher dllWatcher; static void Main(string[] args) { Console.WriteLine("file Watcher Started at " + DateTime.Now.ToString()); fileSystemWatcherDemo watcher = new fileSystemWatcherDemo(); watcher.beginWatcher(); Console.Read(); } private void beginWatcher() { dllWatcher = new FileSystemWatcher(); dllWatcher.Path = @"D:\ScheduledJob\DLL"; dllWatcher.IncludeSubdirectories = false; dllWatcher.Filter = "*.*"; dllWatcher.NotifyFilter = NotifyFilters.LastWrite; dllWatcher.EnableRaisingEvents = true; dllWatcher.Changed += new FileSystemEventHandler(dllWatcher_Changed); } void dllWatcher_Changed(object sender, FileSystemEventArgs e) { try { Console.WriteLine("file" + e.FullPath + "was updated at " + DateTime.Now.ToString()); } catch (Exception ex) { Console.WriteLine("file" + e.FullPath + "can't be updated at " + DateTime.Now.ToString() + ex.Message); } } } }
测试下:运行后,在DLL文件夹中丢一个123.txt,出现如下结果:
发现一个问题,丢一个文件进去,OnChange事件触发了多次(这里是两次),一个文件也被解析执行了多次。
目前这种情况还没有找到彻底解决的办法,而为了保证一次异动,changed事件只触发一次,只能采取一些不是办法的办法来避免。根据这些多次触发的事件是在短时间内完成的特点,这里采用一个键值对,键(文件名称)值(档次执行的时间点)对来记录一个文件异动的时间,当再次触发时,检查这个键值对,找到对应的文件,看它上次执行的时间,如果在设置的特定的时间内,则返回,取消本次执行。
using System; using System.Collections.Generic; using System.IO; namespace fileSystemWatcherDemo { /// <summary> /// FileSystemWatcher 组é件t应|用?Demo /// </summary> class fileSystemWatcherDemo { private FileSystemWatcher dllWatcher; //用于解决同一文件一次异动的多次事件触发问ê题a private Dictionary<string, DateTime> watcherChangedTimes = null; static void Main(string[] args) { Console.WriteLine("file Watcher Started at " + DateTime.Now.ToString()); fileSystemWatcherDemo watcher = new fileSystemWatcherDemo(); watcher.beginWatcher(); Console.Read(); } private void beginWatcher() { watcherChangedTimes = new Dictionary<string, DateTime>(); dllWatcher = new FileSystemWatcher(); dllWatcher.Path = @"D:\ScheduledJob\DLL"; dllWatcher.IncludeSubdirectories = false; dllWatcher.Filter = "*.*"; dllWatcher.NotifyFilter = NotifyFilters.LastWrite; dllWatcher.EnableRaisingEvents = true; dllWatcher.Changed += new FileSystemEventHandler(dllWatcher_Changed); } void dllWatcher_Changed(object sender, FileSystemEventArgs e) { #region 60秒内同一个文件只处理一次
DateTime now = DateTime.Now; int reloadSeconds = 60; if (watcherChangedTimes.ContainsKey(e.FullPath)) { if (now.Subtract(watcherChangedTimes[e.FullPath]).TotalSeconds < reloadSeconds) { return; } else { watcherChangedTimes[e.FullPath] = now; } } else { watcherChangedTimes.Add(e.FullPath, now); } #endregion try { Console.WriteLine("file" + e.FullPath + "was updated at " + DateTime.Now.ToString()); } catch (Exception ex) { Console.WriteLine("file" + e.FullPath + "can't be updated at " + DateTime.Now.ToString() + ex.Message); } } } }
再丢一个文件1.jpg进去,运行结果如下: