125 lines
3.5 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|