在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進去,運行結果如下: