FileSystemWatcher пропускает Created-события

У меня есть FileSystemWatcher, который проверяет несколько каталогов на наличие созданных файлов.

            ((System.ComponentModel.ISupportInitialize)(FileMonitor)).BeginInit();
            FileMonitor.EnableRaisingEvents = true;
            FileMonitor.Created += new FileSystemEventHandler(FileMonitor_Created);
            FileMonitor.Path = Path.ToString();
            FileMonitor.IncludeSubdirectories = true;
            FileMonitor.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.Attributes;
            ((System.ComponentModel.ISupportInitialize)(FileMonitor)).EndInit();

По какой-то причине событие FileMonitor_Created не всегда срабатывает при запуске приложения, хотя должно. Такое ощущение, что случайно...

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

Я попытался установить InterBufferSize для FileMonitor, но это не дало никакого эффекта.

Обновить

Я добавил событие Changed в Filemonitor и дал ему тот же обработчик, что и для события Created. Как-то работает сейчас, хотя файл фактически создается, а не изменяется.

Мне все еще любопытно, почему это всегда работало «по-старому» при установке точки останова.


person Chumbawamba    schedule 25.10.2012    source источник


Ответы (5)


Сколько изменений вы делаете?

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

Взято из MSDN.

person Ian    schedule 25.10.2012
comment
Это всего лишь один файл за раз, InternalBufferSize не должен быть проблемой. - person Chumbawamba; 26.10.2012

Если у вас есть точка останова, она работает, а если нет, то нет?

Вы уверены, что в вашем обработчике событий ничего нет? Как будто происходит исключение, из-за которого программа «чувствует», что ничего не делает? Можете ли вы разместить код в обработчике?

person Haedrian    schedule 25.10.2012

Отделите свою бизнес-логику от события FileMonitor_Created. В событии вы должны сохранить параметры события и возврат. Например. сохранить параметры события в очереди, а затем обработать эти события асинхронно.

person jaccso    schedule 25.10.2012
comment
Я перемещаю файл и запускаю BackgroundWorker (асинхронный) в обработчике, больше ничего. - person Chumbawamba; 26.10.2012

FileMonitor.Created срабатывает, когда файл создан и не заменен предыдущим файлом с той же датой и временем создания.

Сценарий 1) Скопируйте и вставьте тот же файл abc.txt во входную папку без каких-либо изменений в дате создания файла или его содержании — File watcher не распознает файл.

Сценарий 2) Скопируйте и вставьте тот же файл во входную папку с новой датой создания. Наблюдатель за файлами распознает файл.

Таким образом, созданное событие работает со вторым сценарием, возможно, это не ваша ситуация, но для моего первого представления оно выглядит скрытым.

person BMG    schedule 06.11.2012

При возникновении события обработка файла может занять некоторое время. За это время может быть создан другой файл, и обработчик событий не будет обрабатывать второй файл, поскольку он все еще обрабатывает первый файл. Следовательно, второй файл пропущен FileSystemWatcher.

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

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

Я подробно объяснил это с помощью кода в этой статье: FileSystemWatcher пропускает некоторые события

person dok    schedule 09.10.2015