【问题标题】:FileSystemWatcher stops detecting changes c#FileSystemWatcher 停止检测更改 c#
【发布时间】:2017-02-24 22:22:31
【问题描述】:

我设置了一个文件系统观察程序来处理/移动转储到某个位置的文件。前几次我运行它,它运行良好,然后它随机停止检测文件更改。什么可能导致这种情况?我将在下面发布我的代码。

 protected override void OnStart(string[] args)
    {
        fileSystemWatcher1.Path = Config.ToString("WATCHPATH");
        //ignore subfolder changes (error and archive)

        fileSystemWatcher1.IncludeSubdirectories = false;

        //add event handlers
        fileSystemWatcher1.Changed += new FileSystemEventHandler(OnChanged);
        fileSystemWatcher1.Created += new FileSystemEventHandler(OnChanged);
        fileSystemWatcher1.Deleted += new FileSystemEventHandler(OnDeleted);
        fileSystemWatcher1.Renamed += new RenamedEventHandler(OnRenamed);

        //begin watching
        fileSystemWatcher1.EnableRaisingEvents = true;
    }

void OnChanged(object sender, FileSystemEventArgs e)
    {
        try
        {
            FileAttributes attr;
            try
            {
                attr = File.GetAttributes(e.FullPath);
            }
            catch (FileNotFoundException fnfEx)
            {
                //this is here because after you move the file to the archive folder
                //it triggers a change, and can't find the old file.  This ignores changes
                //in subdirectories after moves from main drop folder
                return;
            }

            //this checks if a path is a directory which eliminates circular events being triggered
            if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
            {
                return;
            }
            FileProcessor fp = new FileProcessor();
            fp.Process(e.FullPath);

            DirectoryInfo parentDirectory = System.IO.Directory.GetParent(e.FullPath);
            string archivePath = parentDirectory.FullName + "\\Archive\\" + Settings._sys.User.UserID + "_" + DateTime.Today.Date.ToString("ddMMMMyyyy") + "_" + e.Name;

            if (!Directory.Exists(parentDirectory.FullName + "\\Archive"))
            {
                //create archive directory
                Directory.CreateDirectory(parentDirectory.FullName + "\\Archive");
            }

            //appends number to file if the filename already exists
            if (File.Exists(archivePath))
            {
                string pathOnly = archivePath.Substring(0, archivePath.LastIndexOf('\\'));
                string[] files = Directory.GetFiles(pathOnly, Path.GetFileNameWithoutExtension(archivePath) + "*" + Path.GetExtension(archivePath));
                int x = files.Max(f => GetFileNumber(f)) + 1;
                string fileNameNoExt = e.Name.Substring(0, e.Name.IndexOf("."));
                archivePath = parentDirectory.FullName + "\\Archive\\" + Settings._sys.User.UserID + "_" + DateTime.Today.Date.ToString("ddMMMMyyyy") + "_" + fileNameNoExt + "_" + x.ToString() + ".xlsx";
            }

            fileSystemWatcher1.EnableRaisingEvents = false;
            try
            {
                while (IsFileReady(e.FullPath) != true)
                {
                    Console.WriteLine("Waiting for file to be released by process");
                    continue;
                }
                File.Move(e.FullPath, archivePath);
                File.SetLastWriteTimeUtc(archivePath, DateTime.UtcNow);
            }
            catch (Exception err)
            {
//log error
            }
            fileSystemWatcher1.EnableRaisingEvents = true;

            string msg = string.Format("File {0} | {1}",
                                       e.FullPath, e.ChangeType);
        }
        catch(Exception err)
        {
//logs error
        }
    }

【问题讨论】:

  • 你最好也订阅 Error 事件,这段代码可能不会导致问题。
  • 程序崩溃了吗?
  • 在您的第一个 try 之前添加一个日志条目,只是为了确保它没有检测到更改。如果它每次都写入日志,那么至少您已经消除了未引发的 filewatcher 更改事件,并且实际上可以对您的代码进行故障排除 - 顺便说一下,乍一看似乎很好。
  • 我将日志记录添加为 OnChanged 事件的第一行。对于我的测试,我将一个文件放入监视路径,等待它处理,然后将下一个文件放入(原始文件的克隆)。它处理了前 4 个文件,但甚至没有触发第 5 个文件的日志记录。我试图将 fileSystemWatcher 的 InternalBufferSize 增加到它的最大值(64kb),但我仍然看到同样的问题。

标签: c# .net io filesystemwatcher


【解决方案1】:

这部分代码看起来很关键

        fileSystemWatcher1.EnableRaisingEvents = false;
        try
        {
            while (IsFileReady(e.FullPath) != true)
            {
                Console.WriteLine("Waiting for file to be released by process");
                continue;
            }

它可能会一直处于禁用状态,直到文件未准备好...

【讨论】:

  • 时间可以永远持续下去
  • 不过,这只是猜测
【解决方案2】:

来自documentation

请注意,当超出缓冲区大小时,FileSystemWatcher 可能会错过一个事件。为避免错过活动,请遵循以下准则:

  • 通过设置 InternalBufferSize 属性来增加缓冲区大小。

  • 避免使用长文件名观看文件,因为长文件名会导致缓冲区填满。

  • 考虑使用较短的名称重命名这些文件。

  • 让您的事件处理代码尽可能短。

我会查看第一个和最后一个项目符号。

在我看来,您的事件处理代码不是很短。它包含一个while 循环,可能需要一些时间才能完成。也许事件处理程序应该简单地将路径添加到ConcurrentQueue 并退出。一个单独的工作进程将轮询队列并采取适当的措施。

【讨论】:

  • 我遇到了同样的问题。我不仅错过了一个活动。系统完全停止工作,我没有错误,什么都没有。每次我删除多个文件时它都会停止。我只想落后于行动。我只做日志记录。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多