windows 如何防止 ReadDirectoryChangesW 丢失文件更改

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/57254/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 11:10:38  来源:igfitidea点击:

How to keep ReadDirectoryChangesW from missing file changes

.netwindowsreaddirectorychangesw

提问by

There are many posts on the internet about the ReadDirectoryChangesW API function missing files when there is a lot of file activity. Most blame the speed at which the ReadDirectoryChangesW function loop is called. This is an incorrect assumption. The best explanation I have seen is in the following post, the comment on Monday, April 14, 2008 2:15:27 PM

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

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

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

The summary is that the ReadDirectoryChangesW function reports file changes as they leave the file-write-behind queue, not as they are added. And if too many are added before being committed, you lose notice on some of them. You can see this with your implementation, if you just write a program to generate a 1000+ files in a directory real quick. Just count how many file event notices you get and you will see there are times when you will not receive all of them.

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

The question is, has anyone found a reliable method to use the ReadDirectoryChangesW function without having to flush the volume each time? This is not allowed if the user is not an Administrator and can also take some time to complete.

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

回答by hova

If the API is unreliable, then a workaround may be your only option. That of course likely involves keeping track of lastmodified and filenames. What this doesn't mean is that you need to poll when looking for changes, rather, you can use the FileSystemWatcher as a means to trigger checking.

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

So if you keep track of the last 50-100 times the ReadDirectoryChangesW/FSWevent happened, and you see that it is being called rapidly, you can detect this and trigger the special condition to get all the files that have been changed (and set a flag to prevent future bogus FSW events temporarily) in a few seconds.

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

Since some people are confused in the comments about this solution, I am proposing that you should monitor how fast events are arriving from the ReadDirectoryChangesW and when they are arriving too fast, try to attempt a workaround (usually a manual sweep of a directory).

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

回答by Lompican

We've never seen ReadDirectoryChangesW to be 100% reliable. But, the best way to handle it is separate the "reporting" from the "handling".

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

My implementation has a thread which has only one job, to re-queue all events. Then a second thread to process my intermediate queue. You basically, want to impede the reporting of events as little as possible.

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

Under high CPU situations, you can also impede the reporting of watcher events.

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

回答by Kyokook Hwang

I met same problem. But, I didn't find a solution that guarantee to get all of events. In several tests, I could know that ReadDirectoryChangesW function should be called again as fast as possible after GetQueuedCompletionStatus function returned. I guess if a processing speed of filesystem is very faster than my application processing speed, the application might be able to lose some events.

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

Anyway, I separated a parsing logic from a monitoring logic and placed a parsing logic on a thread.

无论如何,我将解析逻辑与监控逻辑分开,并将解析逻辑放在一个线程上。