代码之家  ›  专栏  ›  技术社区  ›  Jesus Ramos

FileSystemWatcher和Windows7

  •  13
  • Jesus Ramos  · 技术社区  · 15 年前

    我正在编写一个工具,它监视网络目录并正在从Windows Server 2008计算机上运行。如果Windows 7计算机上复制的文件超过19个,则任何不使用Windows 7的计算机都会从网络驱动器上的文件中正确激发FileSystemWatcher的OnChanged事件。(然后不会触发任何事件,尽管如果单独完成文件,它也会工作。是否有解决方法,或者Windows7内核如何处理FSW事件?

    只是澄清一下,当从xp机器复制时,它可以处理数千个文件。(该软件仍在2008服务器上)。

    5 回复  |  直到 8 年前
        1
  •  22
  •   Community Mohan Dere    9 年前

    MSDN :

    Windows操作系统会将文件监视程序创建的缓冲区中的文件更改通知组件。如果在短时间内有许多更改,则缓冲区可能溢出。这会导致组件失去对目录中更改的跟踪,并且只提供覆盖通知。使用 InternalBufferSize 属性很昂贵,因为它来自无法换出到磁盘的非分页内存,所以请将缓冲区保持在足够小但足够大的范围内,以避免错过任何文件更改事件。要避免缓冲区溢出,请使用 NotifyFilter IncludeSubdirectories 属性,以便筛选出不需要的更改通知。

    如果增加缓冲区大小还不够,并且无法控制一次触发事件的文件数,则必须添加额外的轮询。

    另请参见此相关问题:

    FileSystemWatcher does not work properly when many files are added to the directory at the same time…

    更新:

    只增加缓冲区的大小是很有诱惑力的,但这应该小心完成。事实上,在网络访问方面有64K的限制。这个 FileSystemWatcher 类正在使用Windows API函数 ReadDirectoryChangesW 下面有这个限制:

    当缓冲区长度大于64 KB并且应用程序正在通过网络监视目录时,readdirectorychangesw失败,错误为“u invalid”参数。这是由于底层文件共享协议的数据包大小限制造成的。

    如果您想对修改缓冲区大小的成本有更深入的了解,请查看微软的Walter Wang的文章:

    FileSystemWatcher across the network (全文引用如下)

    很抱歉 FileSystemWatcher.InternalBufferSize文件系统观察程序 不是很清楚 监控网络时的缓冲区大小 路径。建议不超过64K 监视网络路径时。

    FileSystemWatcher基本上是一个.NET Win32的包装 readdirectorychangesw api。使用 readdirectorychangesw,您创建和 指定操作系统将要使用的缓冲区 用更改填充。然而, 什么没有提到 readdirectorychangesw文档 (但在 filesystemwatcher docs)是 文件系统创建内部内核 存储更改信息的缓冲区 暂时直到有机会 更新用户缓冲区。大小 创建的内核缓冲区是 与中指定的大小相同 已创建readdirectorychangesw和 在未分页的池内存中。每一次 文件系统监视程序/ 已创建readDirectoryChangesW/ 调用时,新的内核缓冲区也 创建。

    内核内存池(分页和 未分页)在系统中预留 设备驱动程序和的地址空间 要使用的其他内核组件。他们 动态增长和收缩 必要的。当前的大小 去游泳池很容易看到 任务的“性能”选项卡 经理。游泳池会变大 动态直到达到最大值 启动时计算的值 取决于可用系统 资源(主要是RAM)。你不 想要达到这个最大值,否则 各种系统服务和驱动程序 将开始失败。然而,这 计算出的最大值不容易 可用。确定最大值 池大小,您需要使用内核 调试器。如果你对 有关系统的更多信息 内存池,我建议您 看看MSPress Book中的第7章 由所罗门和 Russinovich。

    考虑到这一点,没有 关于缓冲区大小的建议 你可以使用。电流和最大值 系统池的大小将 因客户而异。 不过,你可能不该去 每个文件系统监视程序超过64K/ readdirectorychangesw缓冲区。这个 源于这样一个事实,即 64K限制,网络访问为 记录在ReadDirectoryChangesW中。 但最终你会 对各种应用程序进行测试 目标系统,以便 可以调整缓冲区。

    有与.NET相关联的开销 应用程序和我认为 win32 readdirectorychangesw程序 可能会取得更好的成绩 具有相同缓冲区大小的性能。 但是,速度非常快,而且数量众多 文件更改,缓冲区溢出将 不可避免的,开发商也要走了。 当一个 溢出发生,如手动 枚举要检测的目录 变化。

    总之,filesystemwatcher和 readDirectoryChangesW是一个 轻量级文件更改检测 将要拥有的机制 局限性。更改日记帐是 另一种机制 考虑中等重量的溶液,但是 仍有局限性:

    http://msdn.microsoft.com/en-us/library/aa363798%28VS.85%29.aspx

    重量级解决方案是 写入专用文件系统筛选器 位于文件系统中的驱动程序 堆栈和监视文件系统 变化。当然这是 最复杂的方法。大多数病毒 扫描仪、备份软件和文件 系统监控实用程序,如 文件管理器(www.sysinternals.com) 实现筛选器驱动程序。

    希望上面的解释能帮助你 了解问题的根本原因 你正在经历。请回复 让我们知道你是否需要 更多信息。谢谢您。

        2
  •  4
  •   Justin    15 年前

    在多次尝试使用FileSystemWatcher之后,我放弃了它。它不会正确地触发事件,在错误的时间,错误的类型。老实说,我认为它是.NET框架中最糟糕的类之一。我一直在编写自己的类,它需要一个System.Timer,经过x毫秒后,它将手动检查目录和文件。是的,这需要更多的工作,是的,这可能是一个轻微的皮塔,但一旦你写了它,你可以使用它,无论你想。我希望FileSystemWatcher能像广告中那样工作,但我从未发现它能做到这一点。

        3
  •  2
  •   Laurens Ruijtenberg    15 年前

    大多数情况下,当filesystemwatcher事件触发时,我忽略对象传递的文件,因为此列表可能不完整。

    我只需在FileSystemWatcher对象监视的目录中进行爬行,然后执行手动扫描以查找可能不在FileSystemWatcher缓冲区中的文件。它不是很优雅,但它确保你不会错过一个文件。

        4
  •  0
  •   Jesus Ramos    15 年前

    这是一个非常不可靠的类,当文件超过某个阈值时,在初始副本上触发了大约7次事件,然后当文件传输对话框完成时,我又收到了7个事件,这个问题出现在所有支持FSW的操作系统中。虽然Windows7(还没有尝试过Vista)一次只能接受一个接一个或19个文件,但是如果我将文件从xp机器放到网络驱动器中,我可以一次读取数千个文件,没有任何问题。这可能只是将readdirectorychangesw从xp更改为7。过去的19个文件我无法触发任何事件,所以我想这将成为我工具的一个“特性”。如果有任何人有任何其他信息,请随时作出贡献。

        5
  •  -1
  •   Eric Kung    8 年前

    如果使用MacOSX+Parallels桌面+Windows, 你的代码不起作用, 因为您的filesystemwatcher.path属性是mac路径的目标,所以它是一个unc路径,不受支持!

    它是一个UNC路径,不支持!

    enter image description here

    推荐文章