JD2022-TU1/main/tools/framework/JD.Core/FileWatcherLight.cs

125 lines
3.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace JD.Core
{
public delegate void FilesChangedDelegate(IEnumerable<string> changedFiles);
/// <summary>
/// A light implementation of a file watcher, meant to watch safely a limited number of files.
/// </summary>
public class FileWatcherLight : IDisposable
{
private List<File> _watchedFiles = new List<File>();
private readonly Timer _watchTimer;
private readonly Mutex _watchMutex;
private bool _enabled;
public FileWatcherLight()
{
_watchMutex = new Mutex();
_watchTimer = new Timer(OnWatchTimerElapsed, null, Timeout.Infinite, Timeout.Infinite);
_enabled = false;
}
~FileWatcherLight()
{
Dispose(false);
}
public event FilesChangedDelegate FilesChanged;
public bool Enabled
{
get { return _enabled; }
set
{
_enabled = value;
_watchTimer.Change(_enabled ? 1000 : Timeout.Infinite, Timeout.Infinite);
}
}
public void WatchFile(string filePath, string parentFilePath = null)
{
_watchMutex.WaitOne();
var fileInfo = new System.IO.FileInfo(filePath);
_watchedFiles.Add(new File(filePath, fileInfo.LastWriteTime, parentFilePath));
_watchMutex.ReleaseMutex();
}
public void UnwatchFile(string filePath)
{
_watchMutex.WaitOne();
_watchedFiles = _watchedFiles.Where(file => file.Path != filePath && file.ParentPath != filePath).ToList();
_watchMutex.ReleaseMutex();
}
private void OnWatchTimerElapsed(object dummy)
{
if (FilesChanged != null)
{
_watchMutex.WaitOne();
var changedFiles = new List<string>();
foreach (var file in _watchedFiles)
{
var fileInfo = new System.IO.FileInfo(file.Path);
if (file.Update(fileInfo.LastWriteTime))
{
changedFiles.Add(String.IsNullOrEmpty(file.ParentPath) ? file.Path : file.ParentPath);
}
}
if (changedFiles.Any())
FilesChanged(changedFiles);
_watchMutex.ReleaseMutex();
}
_watchTimer.Change(1000, Timeout.Infinite);
}
private class File
{
private DateTime _modifiedTime;
public File(string path, DateTime modifiedTime, string parentPath = null)
{
Path = path;
_modifiedTime = modifiedTime;
ParentPath = parentPath;
}
public string Path { get; }
public string ParentPath { get; }
public bool Update(DateTime lastWriteTime)
{
if (_modifiedTime.Equals(lastWriteTime))
return false;
_modifiedTime = lastWriteTime;
return true;
}
}
private void Dispose(bool disposing)
{
if (disposing)
{
_watchTimer?.Dispose();
_watchMutex?.Dispose();
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}