简体   繁体   English

如何保持ReadDirectoryChangesW不会丢失文件更改

[英]How to keep ReadDirectoryChangesW from missing file changes

There are many posts on the internet about the ReadDirectoryChangesW API function missing files when there is a lot of file activity. 当有大量文件活动时,互联网上有很多关于ReadDirectoryChangesW API函数丢失文件的帖子。 Most blame the speed at which the ReadDirectoryChangesW function loop is called. 大多数人都指责调用ReadDirectoryChangesW函数循环的速度。 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 我看到的最好的解释是在下面的帖子,评论于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. 摘要是ReadDirectoryChangesW函数报告文件更改,因为它们离开文件后写队列,而不是添加它们。 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. 如果您只是编写一个程序来快速生成目录中的1000多个文件,您可以通过实现看到这一点。 Just count how many file event notices you get and you will see there are times when you will not receive all of them. 只需计算您获得的文件事件通知数量,您就会看到有时您不会收到所有这些通知。

The question is, has anyone found a reliable method to use the ReadDirectoryChangesW function without having to flush the volume each time? 问题是,有没有人找到一种可靠的方法来使用ReadDirectoryChangesW函数而不必每次都刷新卷? This is not allowed if the user is not an Administrator and can also take some time to complete. 如果用户不是管理员并且还可能需要一些时间来完成,则不允许这样做。

We've never seen ReadDirectoryChangesW to be 100% reliable. 我们从未见过ReadDirectoryChangesW 100%可靠。 But, the best way to handle it is separate the "reporting" from the "handling". 但是,处理它的最佳方法是将“报告”与“处理”分开。

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情况下,您还可以阻止观察者事件的报告。

If the API is unreliable, then a workaround may be your only option. 如果API不可靠,那么解决方法可能是您唯一的选择。 That of course likely involves keeping track of lastmodified and filenames. 这当然可能涉及跟踪lastmodified和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. 这并不意味着您需要在查找更改时进行轮询,而是可以使用FileSystemWatcher作为触发检查的方法。

So if you keep track of the last 50-100 times the ReadDirectoryChangesW /FSW event 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到达的速度,以及当它们到达速度太快时,尝试尝试解决方法(通常是手动扫描目录)。

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. 在几个测试中,我可以知道在GetQueuedCompletionStatus函数返回后应该尽快再次调用ReadDirectoryChangesW函数。 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. 我想如果文件系统的处理速度比我的应用程序处理速度快得多,那么应用程序可能会丢失一些事件。

Anyway, I separated a parsing logic from a monitoring logic and placed a parsing logic on a thread. 无论如何,我将一个解析逻辑与监控逻辑分开,并在一个线程上放置一个解析逻辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM