【问题标题】:How to keep ReadDirectoryChangesW from missing file changes如何防止 ReadDirectoryChangesW 丢失文件更改
【发布时间】:2010-09-08 14:33:23
【问题描述】:

互联网上有很多关于 ReadDirectoryChangesW API 函数在有大量文件活动时丢失文件的帖子。大多数都归咎于调用 ReadDirectoryChangesW 函数循环的速度。这是一个不正确的假设。我看到的最好的解释是在下面的帖子中,2008 年 4 月 14 日星期一下午 2:15:27 的评论

http://social.msdn.microsoft.com/forums/en-US/netfxbcl/thread/4465cafb-f4ed-434f-89d8-c85ced6ffaa8/

总结是,ReadDirectoryChangesW 函数在文件更改离开文件后写队列时报告文件更改,而不是在添加时报告。如果在提交之前添加了太多,你会忽略其中一些。如果您只是编写一个程序以真正快速地在目录中生成 1000 多个文件,您可以在您的实现中看到这一点。只要数一数您收到了多少文件事件通知,您就会发现有时您不会收到所有通知。

问题是,有没有人找到一种可靠的方法来使用 ReadDirectoryChangesW 函数而不必每次都刷新音量?如果用户不是管理员,则不允许这样做,并且可能需要一些时间才能完成。

【问题讨论】:

    标签: .net windows readdirectorychangesw


    【解决方案1】:

    如果 API 不可靠,那么解决方法可能是您唯一的选择。这当然可能涉及跟踪 lastmodified 和文件名。 这并不意味着您需要在查找更改时进行轮询,而是可以使用 FileSystemWatcher 作为触发检查的手段。

    因此,如果您跟踪 ReadDirectoryChangesW/FSW 事件发生的最后 50-100 次,并且您看到它被快速调用,您可以检测到这一点并触发特殊条件以获取几秒钟内所有已更改的文件(并设置一个标志以暂时防止未来的虚假 FSW 事件)。

    由于 cmets 中有些人对此解决方案感到困惑,我建议您应该监控事件从 ReadDirectoryChangesW 到达的速度,当它们到达太快时,尝试尝试解决方法(通常是手动扫描目录)。

    【讨论】:

    • 这将在大约 99% 的时间内起作用。如果另一个目录中的文件(除了有很多文件更改的文件)是被跳过的文件,会发生什么。您将扫描一个目录以进行更改,但会错过另一个目录中的单个文件更改。
    • FileSystemWatcher 类是一种包装 ReadDirectoryChangesW 的 .NET 方式,所以不,这没有帮助。
    • 我的回答更多是关于检测一段时间内的事件数以触发 ReadDirectoryChangesW 的解决方法。
    • 并且其中一些事件也将被丢弃并且永远不会到达,就像尝试使用 ReadDirectoryChangesW() 时一样。用 FSW 修饰它没有好处。
    • 不,不是,因为事件包括“文件何时到达”,您永远不会看到。换句话说,原始问题的答案是否定的。除了使用不同的机制(如更改日志或编写文件系统微过滤器)之外,绝对没有解决方法。如何再次使用 ReadDirectoryChangesW() 来弥补它自己的设计缺陷,以某种方式“解决”它?莫名其妙。
    【解决方案2】:

    我们从未见过 ReadDirectoryChangesW 是 100% 可靠的。但是,最好的处理方式是将“报告”与“处理”分开。

    我的实现有一个只有一项工作的线程,用于重新排队所有事件。然后是第二个线程来处理我的中间队列。基本上,您希望尽可能少地阻止事件报告。

    在 CPU 较高的情况下,您还可以阻止观察者事件的报告。

    【讨论】:

    • 由于我没有足够的声誉在上面发表评论,我会说顶级解决方案非常好。在 99% 的情况下,它让你“几乎就在那里”。再添加 1 件事,定期重新扫描您正在查看的文件夹以查找更改。
    【解决方案3】:

    我遇到了同样的问题。但是,我没有找到保证获得所有事件的解决方案。在几次测试中,我知道在 GetQueuedCompletionStatus 函数返回后,应该尽快再次调用 ReadDirectoryChangesW 函数。我想如果文件系统的处理速度比我的应用程序处理速度快得多,应用程序可能会丢失一些事件。

    不管怎样,我把解析逻辑和监控逻辑分开,把解析逻辑放在一个线程上。

    【讨论】:

    • 我使用类似的方法成功解决了这个问题。将事件排队或将它们写入文件以供以后处理。将它们写入磁盘对我来说是关键。这可能看起来很慢,但磁盘被缓存并且开销小于数据库。我的程序每天反映大约 1 TB 的文件更改 - 每天数十万个文件。
    猜你喜欢
    • 2020-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多