FileSystemWatcher停止检测更改c#

时间:2017-02-24 22:22:31

标签: c# .net io filesystemwatcher

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

 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
        }
    }

2 个答案:

答案 0 :(得分:2)

这部分代码看起来很重要

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

它可以保持在禁用状态,直到文件没有准备好......

答案 1 :(得分:0)

来自documentation

  

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

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

  •   
  • 避免观看具有长文件名的文件,因为长文件名有助于填充缓冲区。

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

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

  •   

我会看第一个和最后一个子弹。

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