一般背景
我需要观看100个文件(每个文件的重量约为30KB)。因此,我得出结论,为了保持可靠性,即使FileSystemWatcher
增加到64KB(由于文件大小和快速文件更改),我也不能相信InternalBuffer
。
额外信息
文件是通过第三方发送的,我不能对输入做任何其他事情,比如通过数据库接收数据。显然,我能做的就是聚合文件并随心所欲地做任何事情。
另外,我需要尽可能接近更改时间进行处理。
代码
话虽如此,我创建了一个小型库,用于查找间隔内的变化。
该课程如下:
public delegate void OnSingleFileModified(string filePath);
public delegate void OnFileError(Exception e);
public sealed class FolderMonitor :IDisposable
{
private const int TimerInterval = 10000;
private readonly Timer _timer;
private readonly Dictionary<string, DateTime> _files;
private readonly string _path;
private readonly string _pattern;
private bool _start;
public event OnSingleFileModified OnSingleFileModified;
public event OnFileError OnFileError;
public FolderMonitor(string folderPath, string pattern)
{
_start = true;
_path = folderPath;
_pattern = pattern;
_files = new Dictionary<string, DateTime>();
MapFolder();
_timer = new Timer(TimerInterval)
{
AutoReset = true,
Enabled = _start
};
_timer.Elapsed += CheckChanges;
}
private void MapFolder()
{
if (!Directory.Exists(_path))
return;
IEnumerable<string> files = Directory.EnumerateFiles(_path, _pattern);
foreach (string file in files)
{
DateTime lastWrite = File.GetLastWriteTimeUtc(file);
_files[file] = lastWrite;
}
}
private void CheckChanges(object sender, ElapsedEventArgs el)
{
if (!Directory.Exists(_path))
return;
try
{
_timer.Enabled = false; // prevents multithreating.
IEnumerable<string> files = Directory.EnumerateFiles(_path, _pattern);
foreach (string file in files)
{
DateTime lastWrite = File.GetLastWriteTimeUtc(file);
// if file is new, add it and report
if (!_files.TryGetValue(file, out DateTime prevLastWrite))
{
_files[file] = lastWrite;
OnSingleFileModified?.Invoke(file); // OnFileCreate
continue;
}
if (lastWrite == prevLastWrite)
continue;
// Change detected
_files[file] = lastWrite;
OnSingleFileModified?.Invoke(file); // OnFileModified
}
}
catch (Exception e)
{
OnFileError?.Invoke(e); // OnError
}
finally
{
_timer.Enabled = _start;
}
}
public void Start()
{
_start = true;
_timer.Enabled = true;
}
public void Stop()
{
_start = false;
_timer.Enabled = false;
}
public void Dispose()
{
_timer?.Dispose();
}
}
问题
当它被包装在Windows服务中时,CPU消耗为53%。
怀疑
在路径上调用FileInfo会占用大量CPU。
新的怀疑:Directory.EnumerateFiles(_path, _pattern);
仍然是资源消耗。
有关如何解决此问题的任何建议? 非常感谢。
修改 新代码。
答案 0 :(得分:1)
首先,尝试将模式添加到
string[] files = Directory.GetFiles(_path);
声明,例如
string[] files = Directory.GetFiles(_path, _pattern);
你也可以考虑使用
Directory.EnumerateFiles()
方法,以同样的方式。
string[] files = Directory.EnumerateFiles(_path, _pattern);
因为你可以在返回整个集合之前开始处理它们。