上一篇FileSystemWatcher 監視資料夾和檔案變更
有提到同個變更可能會呼叫數次,這裡就使用List和LINQ來解決
寫個類別紀錄檔案路徑和時間,放在List裡面,超過30秒就從清單中移除
因為我們只是要避免幾十毫秒內的重複觸發,所以其實也可以不用那麼久
private FileSystemWatcher _fileSystemWatcher;
private string monitorPath = "D:\\";
public void Monitor()
{
try
{
if (_fileSystemWatcher == null) _fileSystemWatcher = new FileSystemWatcher();
_fileSystemWatcher.Path = monitorPath;
_fileSystemWatcher.NotifyFilter =
NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.CreationTime;
_fileSystemWatcher.IncludeSubdirectories = false;
_fileSystemWatcher.EnableRaisingEvents = true;
_fileSystemWatcher.Changed += FileChanged; //檔案屬性變更、建立的檔案和刪除的檔案
_fileSystemWatcher.Renamed += FileChanged; //重新命名檔案和資料夾的舊路徑和新路徑
}
catch (Exception exception)
{
}
}
List<FileRecord> _fileRecords = new List<FileRecord>();
private void FileChanged(object sender, FileSystemEventArgs e)
{
string filePath = e.FullPath;
//清理紀錄,移除30秒前紀錄
_fileRecords.RemoveAll(a => a.ChangeTime.AddSeconds(30) < DateTime.Now);
//依照檔案路徑查詢
var file =
from Obsolete in _fileRecords
where Obsolete.FilePath.Equals(filePath)
select Obsolete;
//如果有一樣的檔案
if (file.Any())
{
Console.WriteLine("重複變動的檔案:" + filePath);
}
else
{
Console.WriteLine("第一次變動的檔案:" + filePath);
_fileRecords.Add(new FileRecord(filePath));}
}
class FileRecord
{
public string FilePath;
public DateTime ChangeTime;
public FileRecord(string filePath)
{
FilePath = filePath;
ChangeTime = DateTime.Now;
}
}
這裡用的方式就還不錯,用RemoveAll直接移除,比foreach還快
今天改客戶需求的時候也用LINQ想到的
附上程式碼截圖:
註:後來和老闆討論的時候有談到某些可能的原因,所以可能不用這麼麻煩,只要寫一個字串,判斷內容和現在的檔名一樣就跳過,不一樣則塞進去然後處理就可以了。
但是沒有進行大規模測試,怕軟體交付後才出現問題,所以我暫時是用上面提供的方式
如果大家有比較好的做法或是測試結果,都歡迎留言告訴我,謝謝!
感謝提供思路,
回覆刪除我把[清理紀錄,移除30秒前紀錄]這行的RemoveAll判斷,改換到 if (file.Any()) 區塊內,
避免每次即使沒有重複也在進行多餘的刪除動作
現在回頭看自己以前寫的程式碼,有許多細節都沒有注意到
刪除非常感謝您的建議!讓我有修正文章的機會