FileSystemWatcher и Windows 7 - PullRequest
       1

FileSystemWatcher и Windows 7

13 голосов
/ 15 июля 2010

Я пишу инструмент, который отслеживает сетевой каталог и работает на компьютере с Windows Server 2008, событие OnChanged для FileSystemWatcher корректно запускается из файлов, размещенных на сетевом диске, на любом компьютере, который не использует Windows 7 По какой-то причине, если количество копируемых файлов превышает 19 на компьютере с Windows 7 (сразу), то никакие события не запускаются, хотя это работает, если файлы выполняются по отдельности. Есть ли обходной путь для этого или это то, как ядро ​​Windows 7 ведет себя с событиями FSW?

Просто чтобы прояснить, что это работает для тысяч файлов при копировании с компьютера с XP. (Программное обеспечение все еще находится на сервере 2008 года).

Ответы [ 5 ]

22 голосов
/ 15 июля 2010

С MSDN :

Операционная система Windows уведомляет ваш компонент об изменениях файла в буфере, созданном FileSystemWatcher.Если за короткое время произойдет много изменений, буфер может переполниться.Это приводит к тому, что компонент теряет отслеживание изменений в каталоге, и он будет предоставлять только общее уведомление.Увеличение размера буфера с помощью свойства InternalBufferSize является дорогостоящим, так как оно исходит из невыгружаемой памяти, которую нельзя выгружать на диск, поэтому сохраняйте буфер как небольшой, но достаточно большой, чтобы не пропустить изменение файлаСобытия.Чтобы избежать переполнения буфера, используйте свойства NotifyFilter и IncludeSubdirectories , чтобы можно было отфильтровывать нежелательные уведомления об изменениях.

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

См. Также этот связанный вопрос:

FileSystemWatcher не работает должным образом, когда в каталог одновременно добавляется много файлов…

Обновление:

Может быть заманчиво просто увеличить размер буфера, но это следует делать с осторожностью.На самом деле, ограничение доступа к сети составляет 64 КБ.Класс FileSystemWatcher использует функцию Windows API ReadDirectoryChangesW, которая имеет этот предел:

Сбой ReadDirectoryChangesW с ошибкой ERROR_INVALID_PARAMETER, если длина буфера превышает 64 КБ иПриложение отслеживает каталог по сети.Это связано с ограничением размера пакета базовыми протоколами общего доступа к файлам.

Если вы хотите глубже понять стоимость изменения размера буфера, вам следует взглянуть на статью Уолтера.Ван из Microsoft здесь:

FileSystemWatcher по сети (полный пост цитируется ниже)

Извините, что документацияFileSystemWatcher.InternalBufferSize не очень четко указывал размер буфера при мониторинге сетевого пути.При мониторинге сетевого пути рекомендуется не превышать 64 КБ.

FileSystemWatcher - это, по сути, оболочка .Net для Win32 ReadDirectoryChangesW API.Чтобы использовать ReadDirectoryChangesW, вы создаете и указываете буфер, который ОС будет заполнять изменениями.Однако то, что не упомянуто в документации ReadDirectoryChangesW (но намекается в документации FileSystemWatcher), заключается в том, что файловая система создает внутренний буфер ядра для временного хранения информации об изменениях, пока у нее не появится возможность обновить пользовательский буфер.Размер созданного буфера ядра совпадает с размером, указанным в ReadDirectoryChangesW, и создается в не пейджинговой объединенной памяти.Каждый раз, когда создается / вызывается FileSystemWatcher / ReadDirectoryChangesW, также создается новый буфер ядра.

Пулы памяти ядра (выгружаемые и не выгружаемые) выделяются в системном адресном пространстве для драйверов устройств и другого ядра.компоненты для использования.Они растут и сжимаются динамически по мере необходимости.Текущий размер пулов можно легко увидеть, перейдя на вкладку «Производительность» диспетчера задач.Пулы будут динамически расти, пока не достигнут максимального значения, которое рассчитывается во время загрузки и зависит от доступных системных ресурсов (в основном ОЗУ).Вы не хотите использовать это максимальное значение, иначе начнут выходить из строя различные системные службы и драйверы.Тем не менее, это рассчитанное максимальное значение не легко доступны.Чтобы определить максимальные размеры пула, вам нужно использовать отладчик ядра.Если вас интересует дополнительная информация о пулах системной памяти, я рекомендую вам взглянуть на главу 7 в книге MSPress «Внутри Windows 2000» Соломона и Руссиновича.

С учетом этого нетрекомендация о том, какой размер буфера вы можете использовать.Текущий и максимальный размер системных пулов будет варьироваться от клиента к клиенту.Однако вам, вероятно, не следует превышать 64 КБ для каждого буфера FileSystemWatcher / ReadDirectoryChangesW.Это связано с тем, что существует ограничение в 64 КБ с доступом к сети, как описано в ReadDirectoryChangesW.Но в конце вам придется протестировать приложение на различных ожидаемых целевых системах, чтобы вы могли настроить свой буфер.

С приложениями .Net связаны накладные расходы, и я полагаю, что программа Win32 ReadDirectoryChangesWможет быть в состоянии достичь лучшей производительности с тем же размером буфера.Однако при очень быстрых и многочисленных изменениях файлов переполнение буфера будет неизбежным, и разработчику придется обрабатывать случай, когда происходит переполнение, например, вручную перечислять каталог для обнаружения изменений.

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

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

Решения с большим весом означали бы написание специального драйвера фильтра файловой системы.который находится в стеке файловой системы и отслеживает изменения файловой системы.Конечно, это был бы самый сложный подход.В большинстве антивирусных сканеров, программ резервного копирования и утилит мониторинга файловой системы, таких как filemon (www.sysinternals.com), реализован драйвер фильтра.

Надеюсь, приведенное выше объяснение поможет вам понять причину проблемы, с которой вы столкнулись.переживает.Пожалуйста, ответьте, чтобы сообщить нам, нужна ли вам дополнительная информация.Спасибо.

4 голосов
/ 15 июля 2010

После многих попыток использования FileSystemWatcher я отказался от него. Это не будет запускать события правильно, в неправильное время, неправильный тип. Честно говоря, я думаю, что это один из худших классов в .net Framework. Я всегда заканчивал тем, что писал свой собственный класс, который принимает System.Timer, и по истечении x миллисекунд он будет проверять каталоги, файлы вручную. Да, это требует больше работы, и да, это может быть небольшой PITA, но как только вы написали его, вы можете использовать его где угодно. Хотелось бы, чтобы FileSystemWatcher работал как рекламируется, но я никогда не находил его таковым.

2 голосов
/ 15 июля 2010

В большинстве случаев, когда происходит событие FileSystemWatcher, я игнорирую файлы, передаваемые объектом, поскольку этот список может быть неполным.выполните сканирование вручную, чтобы найти файлы, которые могут отсутствовать в буфере FileSystemWatcher.Это не очень элегантно, но оно гарантирует, что вы не пропустите файл.

0 голосов
/ 13 января 2018

Если вы используете MacOSX + Parallels Desktop + Windows, Ваш код не работает, Поскольку ваше свойство FileSystemWatcher.Path является целевым для пути Mac, это путь UNC, он не поддерживается!

enter image description here

0 голосов
/ 27 июля 2010

Это один действительно ненадежный класс, когда файлы превышают определенный порог, у меня были события, запускающие примерно 7 раз в начальной копии, а затем, когда диалог передачи файла завершен, я получаю еще 7 событий, эта проблема появляется во всех ОС, которые поддерживают FSW. Хотя Windows 7 (еще не пробовала Vista) все еще принимает файлы по одному или по 19 за раз, в то время как, если я перетаскиваю файлы с компьютера с XP на сетевой диск, я могу читать тысячи файлов одновременно без каких-либо проблем. Это может быть просто изменение ReadDirectoryChangesW с XP на 7. В прошлых 19 файлах я не смог запустить ЛЮБЫЕ события, поэтому я предполагаю, что это пока станет «функцией» моего инструмента. Если у кого-то есть другая информация, не стесняйтесь вносить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...