файл изменился: перехватить событие 1 раз
От: gok Россия  
Дата: 16.07.19 17:06
Оценка:
FileSystemWatcher с какой то стати выплескивает 2, 4 сообщения, когда размер файла изменился
Вроде происходит кратное 2-м событие и на сетевом компе в домейне.
Как побороть? try{} finally{} не помогают, сравнение времени событий тоже.
Как еще можно перехватить событие "файл изменился"?
gok
Re: файл изменился: перехватить событие 1 раз
От: Mystic Artifact  
Дата: 16.07.19 18:03
Оценка:
Здравствуйте, gok, Вы писали:

Из простого — слушаете лишнее (NotifyFilters).

Но, прежде всего внимательно и полностью ознакомиться с документацией на MSDN.

Например:

Common file system operations might raise more than one event. For example, when a file is moved from one directory to another, several OnChanged and some OnCreated and OnDeleted events might be raised. Moving a file is a complex operation that consists of multiple simple operations, therefore raising multiple events. Likewise, some applications (for example, antivirus software) might cause additional file system events that are detected by FileSystemWatcher.


Так же, там же написано и то, что оно может пропускать события. Соответственно, необходимо решить допустимо ли это и предпринять соответствующие контрмеры.
Re: файл изменился: перехватить событие 1 раз
От: Mystic Artifact  
Дата: 16.07.19 18:24
Оценка: 8 (2)
Здравствуйте, gok, Вы писали:

В догонку: https://www.codeproject.com/Articles/1220093/A-Robust-Solution-for-FileSystemWatcher-Firing-Eve

Это как пример о решении проблемы дубликатов. Но в целом, мне оно оно не нравится, и советовать его как универсальное не хочется.

Все зависит от ситуации.

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

Ну и так или иначе, т.к. гарантий нет — фактически приходим к тому, что программа должна работать без вотчера, а вотчер использоваться только в помощь существующим механизмам.
Re[2]: файл изменился: перехватить событие 1 раз
От: Sharov Россия  
Дата: 16.07.19 18:38
Оценка:
Здравствуйте, Mystic Artifact, Вы писали:

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


А какие механизмы существует помимо watcher'а?
Кодом людям нужно помогать!
Re[3]: файл изменился: перехватить событие 1 раз
От: Mystic Artifact  
Дата: 16.07.19 18:42
Оценка:
Здравствуйте, Sharov, Вы писали:

S>А какие механизмы существует помимо watcher'а?

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

В случае же непрерывной синхронизации — стандартный периодический поллинг файловой системы. И это вроде как касается всех ОС.

ADD: Это если наше решение гуманно и прикладное. Так то можно: увеличить размер внутреннего буфера (ест память ядра) — может быть решением до определенной (обычно неизвестной) нагрузки. Можно драйвер-фильтр файловой системы сделать и спасибо никто не скажет.
Отредактировано 16.07.2019 18:51 Mystic Artifact . Предыдущая версия .
Re[2]: файл изменился: перехватить событие 1 раз
От: gok Россия  
Дата: 16.07.19 20:47
Оценка:
Здравствуйте, Mystic Artifact, Вы писали:

MA>Здравствуйте, gok, Вы писали:


MA>Из простого — слушаете лишнее (NotifyFilters).


MA>Но, прежде всего внимательно и полностью ознакомиться с документацией на MSDN.


MA>Например:

MA>

Common file system operations might raise more than one event. For example, when a file is moved from one directory to another, several OnChanged and some OnCreated and OnDeleted events might be raised. Moving a file is a complex operation that consists of multiple simple operations, therefore raising multiple events. Likewise, some applications (for example, antivirus software) might cause additional file system events that are detected by FileSystemWatcher.


MA>Так же, там же написано и то, что оно может пропускать события. Соответственно, необходимо решить допустимо ли это и предпринять соответствующие контрмеры.


NotifyFilters.LastWrite
Файл не двигается. Открыли, изменили, закрыли. Пропустить событие можно, некритично. Но больше одного это непрофессионально.
Двойники появляются случайно, но вроде в степени двойки (2, 4).
На "просторах" предлагают затычки для этой баги. Но они не работают.
gok
Re[3]: файл изменился: перехватить событие 1 раз
От: Mystic Artifact  
Дата: 16.07.19 21:15
Оценка: 4 (1)
Здравствуйте, gok, Вы писали:

Я вроде дал объяснение и так довольно развернутое. Даже вырезал кусочек.

gok>NotifyFilters.LastWrite

gok>Файл не двигается. Открыли, изменили, закрыли. Пропустить событие можно, некритично. Но больше одного это непрофессионально.
gok>Двойники появляются случайно, но вроде в степени двойки (2, 4).
gok>На "просторах" предлагают затычки для этой баги. Но они не работают.

Аттрибут файла LastWrite изменяется с *каждым* изменением файла. Т.е. если вы открыли файл, и пишите в него порцию данных — то файловая система вправе изменить его на каждый записанный байт. Разумеется, если бы это было так — то пронаблюдать это было бы крайне сложно (сказывается блочная структура, и журналируемость фс). Просто этот атрибут изменяется *во время записи* файла, а не по его закрытию, как вы возможно думали. Т.е. файл (и запись о нём включая его атрибуты) изменяется ровно тогда, когда он изменяется, разве не логично? И об этом же и сообщает файловая система в виде события.

В довесок к этому, особенности реализации файловой системы, любой антивирус или драйвер-фильтр о существовании которого мы даже не догадываемся — способен создать активность, которая появится тут. Об этом вообще прямо сказано.
Re: файл изменился: перехватить событие 1 раз
От: scf  
Дата: 16.07.19 21:46
Оценка: +1
Здравствуйте, gok, Вы писали:

gok>FileSystemWatcher с какой то стати выплескивает 2, 4 сообщения, когда размер файла изменился

gok>Вроде происходит кратное 2-м событие и на сетевом компе в домейне.
gok>Как побороть? try{} finally{} не помогают, сравнение времени событий тоже.
gok>Как еще можно перехватить событие "файл изменился"?

Проблема в том, что такое "файл изменился". На практике запись в файл не обязана быть атомарной, даже единичный вызов WriteFile может породить несколько событий.

Мой вариант: файл изменился, если а) приходили события о его модификации и б) последние 100мс событий не приходило.
Re[2]: файл изменился: перехватить событие 1 раз
От: Mystic Artifact  
Дата: 16.07.19 21:49
Оценка:
Здравствуйте, scf, Вы писали:

Всё верно, за исключением того, что цифра 100ms взята с потолка и правильный код не может на нее опираться.
Re[2]: файл изменился: перехватить событие 1 раз
От: gok Россия  
Дата: 17.07.19 21:47
Оценка:
Здравствуйте, scf, Вы писали:

scf>Здравствуйте, gok, Вы писали:


gok>>FileSystemWatcher с какой то стати выплескивает 2, 4 сообщения, когда размер файла изменился

gok>>Вроде происходит кратное 2-м событие и на сетевом компе в домейне.
gok>>Как побороть? try{} finally{} не помогают, сравнение времени событий тоже.
gok>>Как еще можно перехватить событие "файл изменился"?

scf>Проблема в том, что такое "файл изменился". На практике запись в файл не обязана быть атомарной, даже единичный вызов WriteFile может породить несколько событий.


scf>Мой вариант: файл изменился, если а) приходили события о его модификации и б) последние 100мс событий не приходило.


The date the file or folder last had anything written to it. (c)NotifyFilters.LastWrite
Какие еще атомы-молекулы? Явно, какая то приблуда-полицай шурует. Двойники появляются только от файла на Network. На VM еще парочка выскакивает. Локальный файл работает норм.
заметил, что изменение файла в VS вообще не порождает это событие! хотя дата файла изменяется...
Вывод: забыть и растереть
gok
Re[3]: файл изменился: перехватить событие 1 раз
От: Mystic Artifact  
Дата: 17.07.19 22:18
Оценка:
Здравствуйте, Sharov, Вы писали:

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

S>А какие механизмы существует помимо watcher'а?
Кстати, если для NTFS — то можно читать журнал ФС, вроде бы API какой-то был, но я с ним никогда не работал. По идее это должно быть железобетонно.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.