C#循环fileInfo导致CPU工作太多

时间:2017-09-18 11:26:55

标签: c# filesystemwatcher

一般背景

我需要观看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);仍然是资源消耗。

有关如何解决此问题的任何建议? 非常感谢。

修改 新代码。

1 个答案:

答案 0 :(得分:1)

首先,尝试将模式添加到

string[] files = Directory.GetFiles(_path);

声明,例如

string[] files = Directory.GetFiles(_path, _pattern);

你也可以考虑使用

Directory.EnumerateFiles()

方法,以同样的方式。

string[] files = Directory.EnumerateFiles(_path, _pattern);

因为你可以在返回整个集合之前开始处理它们。