Как сохранить ReadDirectoryChangesW от пропущенных изменений файла - PullRequest
19 голосов
/ 11 сентября 2008

В Интернете много сообщений о том, что функция API ReadDirectoryChangesW пропускает файлы, когда файловая активность очень велика. Большинство обвиняют в скорости, с которой вызывается цикл функции ReadDirectoryChangesW. Это неверное предположение. Лучшее объяснение, которое я видел, - в следующем посте, комментарии в понедельник, 14 апреля 2008 года, 14:15:27

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

Суть в том, что функция ReadDirectoryChangesW сообщает об изменениях файла, когда они покидают очередь записи файла, а не как они добавляются. И если слишком много добавлено, прежде чем быть зафиксированным, вы теряете уведомление о некоторых из них. Вы можете увидеть это с вашей реализацией, если вы просто напишите программу для создания более 1000 файлов в каталоге очень быстро. Просто посчитайте, сколько файловых уведомлений вы получаете, и вы увидите, что бывают случаи, когда вы не получите их все.

Вопрос в том, нашел ли кто-нибудь надежный способ использования функции ReadDirectoryChangesW без необходимости каждый раз очищать том? Это недопустимо, если пользователь не является администратором, а для его завершения может потребоваться некоторое время.

Ответы [ 3 ]

1 голос
/ 01 октября 2013

Мы никогда не видели, чтобы ReadDirectoryChangesW был на 100% надежным. Но лучший способ справиться с этим - отделить «отчетность» от «обработки».

В моей реализации есть поток, у которого есть только одно задание, чтобы повторно поставить в очередь все события. Затем второй поток для обработки моей промежуточной очереди. По сути, вы хотите как можно меньше препятствовать освещению событий.

В ситуациях с высокой загрузкой ЦП вы также можете препятствовать сообщению о событиях наблюдателя.

1 голос
/ 11 сентября 2008

Если API ненадежен, то обходной путь может быть единственным вариантом. Это, конечно, вероятно, включает в себя отслеживание lastmodified и имен файлов. Что это не значит, что вам нужно опросить при поиске изменений, скорее вы можете использовать FileSystemWatcher как средство для запуска проверки.

Итак, если вы отслеживаете последние 50-100 раз, когда произошло событие ReadDirectoryChangesW / FSW , и вы видите, что оно вызывается быстро, вы можете обнаружить его и вызвать специальное условие, чтобы получить все файлы, которые были изменены (и установите флажок, чтобы временно запретить будущие фиктивные события FSW) в течение нескольких секунд.

Поскольку некоторые люди запутались в комментариях об этом решении, я предлагаю вам следить за тем, как быстро события поступают из ReadDirectoryChangesW, а когда они поступают слишком быстро, попробуйте попробовать обходной путь (обычно ручное сканирование каталог).

0 голосов
/ 24 мая 2012

Я встретил ту же проблему. Но я не нашел решения, которое гарантировало бы получение всех событий. В нескольких тестах я мог знать, что функция ReadDirectoryChangesW должна вызываться снова как можно быстрее после возврата функции GetQueuedCompletionStatus. Я предполагаю, что если скорость обработки файловой системы очень высока, чем скорость обработки моего приложения, приложение может потерять некоторые события.

В любом случае, я отделил логику анализа от логики мониторинга и поместил логику анализа в поток.

...