文件系统监视器问题

3
我正在尝试使用FileSystemWatcher - 并且有一些进展。
目标是将创建的文件从受监视的文件夹移动到一个新文件夹。
但是...遇到了两个问题。首先,如果我一次将3个文件移动到一个文件夹中(选择3个文件,按下ctrl+x,然后按下ctrl+c到我的Monitor文件夹),监视器只会触发第一个文件。其他两个不会被处理。
            FileSystemWatcher fsw = new FileSystemWatcher(FolderToMonitor);
        fsw.Created += new FileSystemEventHandler(fsw_Created);

        bool monitor = true;

        while (monitor)
        {
            fsw.WaitForChanged(WatcherChangeTypes.All, 2000);
            if (Console.KeyAvailable)
            {
                monitor = false;
            }
        }

        Show("User has quit the process...", ConsoleColor.Yellow);
        Console.ReadKey();

有没有办法让它看到所有3个文件夹?

其次,如果我将文件从另一个驱动器移动到监视文件夹中,需要几秒钟的时间将文件复制到文件夹中。然而,监视器在文件开始复制时就会触发..因此,它是只读的,还没有准备好被移动。

有没有办法在处理文件之前等待文件完成复制到监视文件夹中?


我犯了一个错误...它不是只读的...错误在于该进程无法访问文件,因为它正在被另一个进程使用。在代码中有没有一种方法可以检查这个问题? - Craig
1个回答

3
根据MSDN文档
Windows操作系统通过FileSystemWatcher创建的缓存向组件通知文件更改。如果短时间内有很多更改,则缓存可能会溢出。这将导致组件无法跟踪目录中的更改,并且仅提供一般通知。通过设置InternalBufferSize属性增加缓存大小是昂贵的,因为它来自无法交换到磁盘的非分页内存,因此请将缓存保持足够小但不会错过任何文件更改事件。为避免缓冲区溢出,请使用NotifyFilter和IncludeSubdirectories属性过滤掉不需要的更改通知。
也许这就解释了您的问题?另请注意,将文件从一个目录剪切并粘贴到另一个目录基本上只是一个重命名操作,因此您应该使用Renamed事件来检测它们。
至于您的其他问题:尝试使用Changed事件与Created事件一起使用,因为我认为对于一个文件,两者都只会被引发一次(请注意,将文件从另一个驱动器移动不是简单的重命名操作:它是复制和删除),因此Changed事件应该指示文件复制操作何时完成(即在文件完成后才触发)。

请注意,如果有其他进程将文件写入目标目录(除了剪切/粘贴),可能会触发多个“已更改”事件,并且在第一个事件之后文件仍可能正在使用。 - C.Evenhuis
谢谢@ShdNx - 我一次只复制了3个文件...这会导致溢出吗,还是他们在说缓冲区填满之前有数百个文件?对我来说非常不明确。我会研究Changed事件。我本来想作弊,使用一个While循环尝试以写模式打开文件...然后如果有异常,就假定为只读...等待一段时间,再次尝试,直到我可以成功以写模式打开它(File.Open),那么这意味着文件没问题。这种方法有很多问题吗? - Craig
@cdotlister:说实话我不太确定。我建议尝试增加缓冲区大小(比如将其乘以2),然后检查是否收到更多通知。此外,您应该尝试订阅所有公开的事件(除了Disposed),只是为了看看是否有您错过的内部IO操作。那个while循环听起来像个恶魔般的想法,但有时它是唯一可行的选择。如果其他方法都不起作用,您不应该害怕使用邪恶的解决方案,但请记住(并在代码中添加注释),它是不好的,并且应该尽可能避免。 - ShdNx
1
你可以通过订阅 OnError 事件并检查事件参数中的异常类型来确定是否出现 InternalBufferOverflowException。 - Brad Barker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接