Sairam Kannan Ответов: 4

Наблюдатель файловой системы иногда не подбирает файлы должным образом даже если служба окон работает должным образом


Всем Привет,

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

Теперь у меня есть два потока - основной поток(служба окон) и рабочий поток(очередь). Наблюдатель файловой системы находится в основном потоке, и созданное событие настраивается для обработки файлов. Для объекта-наблюдателя, уведомить фильтра=именем;исполнение фильтра=*.в формате XML;включать подкаталоги=ложь;внутренний буфер=32768.

Now when processing file i just get filename from filesystem watcher of main thread and provide it to worker thread(it is a background thread). In this worker thread i use queue concept where i will queue up files then process them one by one, when queue count > 0 then return back to watching folder step processing of all files is done.I opted for this strategy, since i gone through several sites and came to know buffer overflow might occur causing files not recognized. (Note:Files come from an external system - have no idea if file transfer is by move or copy or ftp) But still on initial stages of testing when external system was involved there was no issues.

Но, к сожалению, через 15 дней или около того я просто включил логику проверки в соответствии с запросом клиента, ни один из оставшихся кодов не был затронут, но иногда файлы остаются в исходной папке без обработки. если я проверю сервис, то он будет в рабочем состоянии. Если я вырезаю и вставляю файл в исходную папку, то происходит запуск события и оно обрабатывается.Это не происходит в моей среде разработки, когда я запускаю код и проверяю его. Но это происходит в моей тестовой среде, где я развернул свое приложение.

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

Потому что папка сталкивается только с несколькими файлами, и они будут только около 10-15 КБ. я не верю, что причиной может быть переполнение буфера. И я не знаю, изменила ли внешняя система способ размещения файла в моей исходной папке.

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

Пожалуйста, помогите мне решить эту проблему. Так как он скоро выйдет в эфир. Клиент уже жалуется на эту проблему на этапе UAT в тестовой среде.

Заранее спасибо.

********Обновление 12-04-2013 10:42 вечера*********

Получил информацию от внешней системы о том, что передача файлов происходит по FTP. Нет никаких улучшений, даже если размер буфера увеличился с 32 Кб до 48 КБ. Теперь этот выбор файлов-единственная проблема, с которой сталкивается клиент. Все остальные необходимые функции, выполняемые приложением, успешно очищаются.

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

4 Ответов

Рейтинг:
28

Ian A Davidson

Мне очень жаль, что я увидел этот вопрос только сегодня. У меня есть несколько лет опыта работы с FileSystemWatcher (и с функциями Win32 API при использовании C++ до C#).

Это основные области, на которые следует обратить внимание:

1) Как вы уже сказали, убедитесь, что код, обрабатывающий уведомления, работает как можно быстрее, чтобы потенциально не пропустить уведомления. Лучшим решением, опять же, как вы указали, является добавление пути в "очередь", которая затем обрабатывается в другом потоке. (Вы должны убедиться, что ваши очереди управляются потокобезопасным способом. Используйте удобную функцию синхронизации).

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

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

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


Чтобы преодолеть и справиться с этими проблемами и ограничениями, где я использовал FileSystemWatcher, я получил не менее 3 (моих собственных) потоков, 2 очереди и словарь!
Боюсь, что я не смогу опубликовать сам код, так что вот мое описание этого кода:

Нити:
1) основной поток приложения-это то место, где создается FileSystemWatcher, а также другие 3 потока.
2) поток, который обрабатывает очереди.
3) поток, который ничего не делает, но ждет и часто проверяет (каждую минуту в моем случае), что FileSystemWatcher все еще работает.
4) временный поток, используемый при запуске (или повторной инициализации) для добавления существующих файлов в очередь "измененных".

Очереди:
1) очередь строк для "измененных" (или созданных) путей к файлам.
2) очередь строк для "удаленных" путей к файлам.

Словарь с путем к файлу в качестве ключа, содержащий информацию (например, время последнего изменения и размер файла) для каждого файла.


Реагируйте на события FileSystemWatcher следующим образом:

Изменено / создано: добавьте "полный путь" в очередь "изменено".
Удаленный: Добавьте "полный путь" в очередь "удалено".
Переименованы: добавить "OldFullPath" на "удален" очереди, и "пути" для "изменил" очереди.
OnError: зарегистрируйте исключение и убедитесь, что "EnableRaisingEvents" имеет значение false.

Затем мой второй поток запускается в цикле, чтобы выполнить некоторую работу каждые настраиваемые миллисекунды, чтобы обработать очереди следующим образом:
1) пройдите через очередь "удаленных" путей, для каждого пути удалите ее из очереди и удалите запись для пути в словаре, если он существует.
2) аналогичным образом пройдите через очередь "измененных" путей и добавьте (или обновите) информацию о файле в словаре.
3) пройдите каждый путь в словаре:
а) проверьте, не превышает ли последнее измененное время, хранящееся в информации, заданное число миллисекунд. Если это так, то
б) убедитесь, что размер файла не изменился с момента последней проверки информации (и обновите его). Если она не изменилась, то
в) проверьте, что файл не заблокирован, попытавшись временно открыть его для чтения-записи. Если это удастся
г) обработайте файл (сделайте с ним все, что вам нужно) и
д) наконец, добавьте путь к файлу в очередь "удалено".

Мой третий поток всегда инициализируется сразу после FileSystemWatcher. Он использует те же параметры фильтрации, чтобы пройти через просматриваемую папку, добавляя любые найденные файлы в очередь "изменено". Этот поток завершается, когда он закончился.

My fourth and final thread runs for the lifetime of the service like the first two. It is another loop with a waiting time (e.g. 1 minute). Each time it enters the loop, it checks that the FileSystemWatcher is active (EnableRaisingEvents is true - hence why I ensure it is forced back to false in OnError). If this is false, it checks that the folder to watch exists. If the folder does not exist it will log a warning, and then go back round the loop, i.e. wait for a minute and then check again. If/when the folder does exist, it will call the initialisation method, which recreates the FileSystemWatcher and runs the third thread (to check for existing files), and then log an information message to say that the file system watcher was successfully reset. (If reset fails, an error is logged, and this thread will exit because there's no point continuing).


Ну, это довольно длинное описание, но я надеюсь, что оно поможет.

С уважением,
Иан.


Ian A Davidson

Опять же, кто-то голосует против, не комментируя почему. Это очень разочаровывает. Если что-то не так с моей статьей, пожалуйста, скажите об этом.
Спасибо,
Иан.

H.Brydon

Хорошее усилие, хорошее объяснение...

+5 от меня, чтобы частично компенсировать...

Sairam Kannan

Спасибо Яну за ваш ответ и советы. Это поможет в будущем как мне, так и другим программистам. Я обработал большинство случаев, которые вы указали, поскольку я уже выполнил необходимый анализ по той причине, что я видел многие проблемы в существующем приложении, использующем FileSystemWatcher в моем проекте. Таким образом, нет ничего особенного, что можно было бы считать упущенным...кроме использования нескольких потоков и потока опроса. Я выбрал только 2 потока, так как это было небольшое приложение, а что касается опросного потока, то он не сталкивается с большими нагрузками, поэтому его можно было обрабатывать только с парой потоков.

Coxianuk

Еще раз спасибо! Я справился с большинством сценариев, однако сетевой сбой и проблема внутреннего буфера мешали мне.

Рейтинг:
2

Sergey Alexandrovich Kryukov

Это на самом деле не "решение", но то, о чем вам лучше знать; пожалуйста, смотрите эти статьи CodeProject:
FileSystemWatcher - чистый хаос (Часть 1 из 2)[^],
FileSystemWatcher - чистый хаос (Часть 2 из 2)[^].

—СА


Рейтинг:
13

Sairam Kannan

Hi All,

After couple of days i was able to find a solution by replicating the same scenario in my development enviroment just the way it was on my test environment. I requested the team member of external system to FTP sample file i post from my archive test files to my polling folder.

I have previously read in msdn where it states that files that are copied or moved may sometime only will be recognised as RENAMED event. Felt this might be applicable and so apart from CHANGED event, i also included RENAMED event to process files. This solved my issue and no files are getting clogged now in polling folder.

Replicating issue is one thing helped me. And another way to crack your issue while dealing with filesystemwatcher concepts in your coding is to use small project to test your case by monitoring the folder you watch for changes and note them down. So you can construct code accordingly.

Thanks


Рейтинг:
0

eqxvip

Привет!
У меня была та же проблема, и, прочитав ваше решение, я понял почему. В нашем коде мы слушаем созданную фильтрацию событий по XML-файлам, как и вы. Это событие всегда срабатывает, но поскольку большинство программ SFTP поддерживают продолжение при ошибках, файлы создаются с использованием временного расширения типа .часть и .TMP или что-то подобное, чтобы затем быть переименованным, когда он будет полностью перенесен. Именно по этой причине ваше переименованное событие с фильтром на XML попадает в ваш код, поскольку файл не называется XML до тех пор, пока не будет переименован.
Ваш,
Лассе С. Йенсен