FileSystemWatcher vs опитування, щоб спостерігати за змінами файлів


152

Мені потрібно налаштувати додаток, який спостерігає за файлами, що створюються в каталозі, локально або на мережевому диску.

Буде FileSystemWatcherнайкращим варіантом чи опитування за таймером. Я використовував обидва методи в минулому, але не широко.

Які проблеми (продуктивність, надійність тощо) виникають у будь-якого методу?


3
FileSystemWatcher - це хитра абстракція, і на неї не можна покластися, окрім самих основних випадків. Дивіться тут: stackoverflow.com/a/22768610/129130
Stein Åsmul

1
Хочете додати посилання для посилання на цю відповідь від Реймонда Чена (експерта Microsoft) на тему надійності FileSystemWatcher . І його блог: Стара нова річ (наприклад, шукайте FileSystemWatcher).
Stein Åsmul

Відповіді:


105

Я бачив, як спостерігач файлової системи вийшов з ладу у виробничих та тестових середовищах. Зараз я вважаю це зручністю, але не вважаю його надійним. Моя модель полягає в тому, щоб спостерігати за змінами за допомогою спостерігача файлової системи, але час від часу запитуйте, щоб знайти застарілі зміни файлів.

Редагувати: Якщо у вас є інтерфейс користувача, ви також можете надати користувачеві можливість "оновити" зміни замість опитування. Я б поєднав це з динаміком файлової системи.


11
Я бачив, якщо теж впаде. Ми використовували рішення, щоб обернути власний клас, де клас обгортки ТАКОЖ використовує таймер, щоб перевірити, що спостерігач все ще працює.
Joel Coehoorn

Ми робимо щось подібне - після того як ми обробили файл, переданий у події FileCreate, перед тим, як повернутись, ми перевіримо будь-які інші файли вручну. Це, здається, зменшує будь-які проблеми, що виникають із великою кількістю файлів, що надходять одночасно.
Джон Сіблі

4
Я вважаю, що ми перевірили його в XP та Server 2003 на локальному каталозі та спільній доступності файлів, і у нас були машини XP. У нас виникли проблеми з місцевим режимом і файлами. Однією з вірогідних причин, до якої ми придумали, було копіювання / створення багатьох файлів за короткий проміжок часу в каталозі.
Джейсон Джексон

5
Це не дуже конструктивно і не професійно, щоб просто заявити, "я бачив привид одного дня". Здається, що люди внизу, згадуючи документ msdn про перевиконання нестабільних буферів, можуть пояснити ваші проблеми. Ви намагалися використовувати підхід Брента?
v.oddou

4
Я щойно купив датчик газу на Amazon, і мене вразило, скільки людей сказали, що він не працює, коли вони, очевидно, не правильно його відкалібрували або навіть не знали про калібрування ... FileSystemWatcher має відомі обмеження з високим трафіком від її розмір буфера. Майже гарантовано, що це причина "провалу". Це легко пояснюється в документації, і існують робочі місця, які забезпечують дуже надійну роботу (як розміщено нижче). Це не є гарною відповіддю, щоб просто сказати: "Помилка. Щось щось не вийшло, не знаю, чому ... ніхто не повинен на це покладатися".
u8it

60

Найбільшою проблемою у мене були відсутні файли, коли буфер заповнюється. Легкий як пиріг для виправлення - просто збільште буфер. Пам’ятайте, що він містить назви файлів та події, тому збільште його до очікуваної кількості файлів (проб і помилок). Він використовує пам'ять, яку неможливо випустити на екран, тому вона може змусити інші процеси створювати сторінку, якщо пам'ять втрачається.

Ось стаття MSDN про буфер: FileSystemWatcher .. ::. Властивість InternalBufferSize

На MSDN:

Збільшення розміру буфера коштує дорого, оскільки воно виходить із пам'яті, що не піддається тимчасовому підключенню, яку неможливо замінити на диск, тому зберігайте буфер якомога менше. Щоб уникнути переповнення буфера, використовуйте властивості NotifyFilter та IncludeSubdirectories, щоб відфільтрувати сповіщення про небажані зміни.

Ми використовуємо 16 Мб завдяки великій партії, яка очікується за один раз. Добре працює і ніколи не пропускає файл.

Ми також читаємо всі файли, перш ніж почати обробляти навіть один ... дістаємо імена файлів, які безпечно кешуються (у нашому випадку - в таблицю бази даних), а потім обробляємо їх.

Для проблем із блокуванням файлів я породив процес, який очікує розблокування файлу, очікуючи одну секунду, потім дві, потім чотири та ін. Ми ніколи не опитуємось. Це було без помилок на виробництві вже близько двох років.


12
Переповнення буфера? О, ви маєте на увазі переповнення стека.
TheFlash

1
Станом на .NET 3.5: "Ви можете встановити буфер у 4 Кб або більше, але він не повинен перевищувати 64 КБ"
brad

9
Як ви використовуєте 16 Мб, якщо максимальний внутрішній буфер для FileSystemWatcher становить 64 КБ?
BK

1
@ Jarvis, буфер - це місце для зберігання даних, налаштоване для зберігання інформації під час передачі, поки вона не може бути оброблена. Це зазвичай означає FIFO або чергу, оскільки ви хочете обробляти запити в тому порядку, коли вони надходять, але в деяких процесах, таких як рекурсія в програмах використовуються структури FILO або Stack. У цьому випадку ми, безумовно, маємо на увазі буфер черги подій, а не буфер стека викликів програм
MikeT

1
petermeinl.wordpress.com/2015/05/18/tamed-filesystemwatcher Ця публікація ділиться надійними обгортками навколо стандартного FileSystemWatcher (FSW), виправляючи проблеми, які часто виникають під час його використання для моніторингу файлової системи в реальних програмах.
Кікенет

35

Також FileSystemWatcherможна пропустити зміни під час зайнятості, якщо кількість змін у черзі переповнює наданий буфер. Це не обмеження самого класу .NET, а базової інфраструктури Win32. З нашого досвіду, найкращий спосіб мінімізувати цю проблему - це якнайшвидше скасувати сповіщення та вирішити їх з іншого потоку.

Як згадував @ChillTemp вище, спостерігач може не працювати на акціях, що не належать до Windows. Наприклад, він зовсім не працюватиме на встановлених накопичувачах Novell.

Я погоджуюся, що хороший компроміс - це робити епізодичне опитування, щоб зібрати будь-які пропущені зміни.


4
Оглядач файлової системи може почати збирати безліч подій швидко. Якщо ви не зможете виконати обробник подій принаймні так швидко, як вони будуть звільнені, з часом обробник почне скидати події на підлогу, і ви пропустите речі.
Брент Роквуд

17

Також зауважте, що спостерігач файлової системи не є надійним для загальних файлів. Особливо, якщо спільний доступ до файлів розміщений на сервері, який не є Windows. ЖКС не слід використовувати для нічого критичного. Або слід використовувати з епізодичним опитуванням, щоб переконатися, що він нічого не пропустив.


3
Чи визнала Microsoft, що вона не є надійною для файлових файлів, що не мають Windows? Ми, звичайно, відчуваємо цю першу руку з моменту переходу з загальної частки Windows на частку SMB на базі Linux.
Шон

1
Не те, що мені відомо. І я впевнений, що це була б просто винна гра між різними постачальниками.
холодний час

1
У нас виникли проблеми з спостерігачем файлової системи на картах накопичувачів. Якщо карта відключиться, а потім повторно підключиться, спостерігач файлів більше не викликає змін. Легко вирішується, але все ж страйк проти спостерігача файлової системи IMHO.
Річард Дорман

11

Особисто я користувався FileSystemWatcherвиробничою системою, і вона спрацювала чудово. За останні 6 місяців у нього не було жодної гикавки 24x7. Це моніторинг однієї локальної папки (яка є спільною). У нас відносно невелика кількість файлових операцій, з якими вона має оброблятись (10 подій, знятих на день). Це не те, про що мені колись доводилося хвилюватися. Я б знову скористався, якби переробити рішення.


7

Зараз я використовую FileSystemWatcherXML-файл, що оновлюється в середньому кожні 100 мілісекунд.

Я виявив, що доки FileSystemWatcherправильно налаштовано, ви ніколи не повинні мати проблем з локальними файлами.

Я не маю досвіду перегляду віддалених файлів та спільних для Windows.

Я вважаю, що опитування файлу буде зайвим і не вартує накладних витрат, якщо ви за своєю суттю не довіряєте FileSystemWatcherабо безпосередньо не відчували обмежень, які всі інші перераховували тут (не для спільних акцій Windows, а також для віддаленого перегляду файлів).


5

Я б пішов на опитування.

Проблеми з мережею викликають FileSystemWatcherненадійність (навіть при перевантаженні події помилки).


5

У мене виникли проблеми з використанням FileSystemWatcherмережевих акцій. Якщо ви перебуваєте в чистому середовищі Windows, це може не бути проблемою, але я спостерігав за подією NFS, і оскільки NFS є без громадянства, жодного разу не було повідомлень про зміну файлу, який я переглядав.


Я потрапив у ту саму проблему, але для мене це було несподівано, оскільки FileSystemWatcher був на тому ж сервері Windows, який ділиться папкою за допомогою NFS. факт спільного використання папки з NFS призводить до того, що диспетчер файлів не бачить файлів, створених за допомогою спільного доступу, віддалено (тобто з Linux, який відображає спільне використання), тоді як якщо я пишу файл у тій самій папці під моніторингом, файлова система запускається. схоже, сервер NFS записує файли за допомогою нижнього шару, а шар api, який запускає, якщо дисертація файлової системи не задіяна, хтось має більше інформації?
Mosè Bottacini

3

У мене виникли великі проблеми з FSW на мережевих накопичувачах: Видалення файлу завжди кидало подію помилки, ніколи не видаляла подію. Я не знайшов рішення, тому зараз уникаю ЖКС і використовую опитування.

Події створення, з іншого боку, спрацювали чудово, тому якщо вам потрібно лише стежити за створенням файлів, ви можете перейти до FSW.

Крім того, у мене зовсім не було проблем із локальними папками, незалежно від того, поділялися вони чи ні.


3

Повернувшись із методу події якнайшвидше, використовуючи інший потік, вирішили для мене проблему:

private void Watcher_Created(object sender, FileSystemEventArgs e)
{
    Task.Run(() => MySubmit(e.FullPath));
}

2

На мою думку, використання ЖКС та опитування - це марна трата часу та ресурсів, і я здивований, що досвідчені розробники пропонують це. Якщо вам потрібно скористатися опитуванням, щоб перевірити наявність будь-яких пропусків ЖКС, то, природно, ви можете взагалі відмовитись від ЖКС і використовувати лише опитування.

Наразі я намагаюся вирішити, чи буду використовувати ЖКС чи опитування для проекту, який розробляю. Читаючи відповіді, очевидно, що є випадки, коли ЖКС повністю задовольняє потреби, в той час як в інших випадках потрібно опитування. На жаль, жодна відповідь насправді не стосувалася різниці в продуктивності (якщо вона є), лише з питаннями "надійності". Хтось може відповісти на цю частину питання?

EDIT: Точка nmclean щодо обґрунтованості використання як ЖКС, так і опитування (ви можете прочитати обговорення в коментарях, якщо вас цікавить) представляється дуже раціональним поясненням, чому можуть виникнути ситуації, коли використання ЖКС та опитування є ефективний. Дякую, що ви пролили світло на мене (і хтось інший, хто має таку ж думку), nmclean .


1
Що робити, якщо ви хочете відповісти на зміни файлів якомога швидше? Наприклад, якщо ви запитуєте один раз на хвилину, можливо, у вас буде затримка на 1 хвилину між зміною файлу та завантаженням програми на зміну. Імовірно, подія ЖКС буде ініційована значно раніше. Таким чином, використовуючи обидва, ви поводитесь з подіями з якомога меншою затримкою, але також збираєте пропущені події, якщо такі є.
rom99

@ rom99 Точно моя думка. Якщо ЖКС недостовірний у випадках, коли вам потрібна швидка реакція, немає сенсу використовувати її, оскільки у вас будуть випадки, коли швидкої реакції не буде, таким чином, ваша заявка буде ненадійною. Те, що вам потрібно зробити, буде опитуватись у коротших інтервалах у потоці. Виконуючи те й інше , ви маєте толерантність у часи відповіді, яку охоплює опитування, то чому б не використовувати лише опитування?
Грім

5
@ThunderGr "таким чином, ваша заявка буде ненадійною". - У багатьох випадках швидкість не є необхідною умовою надійності. Роботу треба виконати, але це може зачекати деякий час. Якщо ми поєднаємо повільне та надійне опитування з швидкою, ненадійною ЖКС, ми отримаємо програму, яка завжди є надійною, а іноді й швидкою, яка є кращою, ніж надійною та ніколи не швидкою. Ми можемо видалити ЖКС і досягти такого ж максимального часу відгуку, здійснюючи постійне опитування, але це відбувається за рахунок чутливості решти програми, тому це слід робити лише в тому випадку, якщо потрібна негайна відповідь.
nmclean

2
Тепер, чому вищезгаданий поганий аргумент? Тому що, хоча нам ще потрібен доступ до диска, він нам потрібен менше . Так само ви можете опитувати менше. Тільки тому, що ми все ще перевіряємо всі файли, це не означає, що навантаження однакова. Твоє твердження: "опитування коштує дорого за час процесора з FSW чи ні", помилкове . Вивантаживши занепокоєння "безпосередність" для ЖКС, ми можемо змінити опитування на непрацююче завдання з низьким пріоритетом, таким чином, що напруженість програми в будь-який момент різко знизиться , надаючи при цьому "лікування" безпосередності. Ви просто не можете досягти однакового балансу при одиночному опитуванні.
nmclean

9
@nmclean Дякую, що витратили час та енергію, щоб пояснити це так, як ви це зробили. Якщо ви поставите це так, це, безумовно, має набагато більше сенсу. Так само, як бувають випадки, коли кеш не підходить до вашої конкретної проблеми, тому FSW (коли це виявиться ненадійним) може бути непридатним. Виявляється, ви весь час були праві. Мені шкода, що мені знадобилося стільки часу, щоб отримати.
Грім

1

Робоче рішення для роботи зі створенням події замість зміни

Навіть для копіювання, вирізання, вставки, переміщення.

class Program
{        

        static void Main(string[] args)
        {
            string SourceFolderPath = "D:\\SourcePath";
            string DestinationFolderPath = "D:\\DestinationPath";
            FileSystemWatcher FileSystemWatcher = new FileSystemWatcher();
            FileSystemWatcher.Path = SourceFolderPath;
            FileSystemWatcher.IncludeSubdirectories = false;
            FileSystemWatcher.NotifyFilter = NotifyFilters.FileName;   // ON FILE NAME FILTER       
            FileSystemWatcher.Filter = "*.txt";         
             FileSystemWatcher.Created +=FileSystemWatcher_Created; // TRIGGERED ONLY FOR FILE GOT CREATED  BY COPY, CUT PASTE, MOVE  
            FileSystemWatcher.EnableRaisingEvents = true;

            Console.Read();
        }     

        static void FileSystemWatcher_Created(object sender, FileSystemEventArgs e)
        {           
                string SourceFolderPath = "D:\\SourcePath";
                string DestinationFolderPath = "D:\\DestinationPath";

                try
                {
                    // DO SOMETING LIKE MOVE, COPY, ETC
                    File.Copy(e.FullPath, DestinationFolderPath + @"\" + e.Name);
                }
                catch
                {
                }          
        }
}

Рішення для цього спостерігача файлів під час події зміни атрибутів файлів за допомогою статичного зберігання

class Program
{
    static string IsSameFile = string.Empty;  // USE STATIC FOR TRACKING

    static void Main(string[] args)
    {
         string SourceFolderPath = "D:\\SourcePath";
        string DestinationFolderPath = "D:\\DestinationPath";
        FileSystemWatcher FileSystemWatcher = new FileSystemWatcher();
        FileSystemWatcher.Path = SourceFolderPath;
        FileSystemWatcher.IncludeSubdirectories = false;
        FileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite;          
        FileSystemWatcher.Filter = "*.txt";         
        FileSystemWatcher.Changed += FileSystemWatcher_Changed;
        FileSystemWatcher.EnableRaisingEvents = true;

        Console.Read();
    }     

    static void FileSystemWatcher_Changed(object sender, FileSystemEventArgs e)
    {
        if (e.Name == IsSameFile)  //SKIPS ON MULTIPLE TRIGGERS
        {
            return;
        }
        else
        {
            string SourceFolderPath = "D:\\SourcePath";
            string DestinationFolderPath = "D:\\DestinationPath";

            try
            {
                // DO SOMETING LIKE MOVE, COPY, ETC
                File.Copy(e.FullPath, DestinationFolderPath + @"\" + e.Name);
            }
            catch
            {
            }
        }
        IsSameFile = e.Name;
    }
}

Це вирішення вирішення цієї проблеми з декількома подіями, що викликають події.


0

Я б сказав, використовуйте опитування, особливо в сценарії TDD, оскільки набагато простіше знущатись / стримувати наявність файлів або іншим чином, коли викликається подія опитування, ніж покладатися на більш "неконтрольовану" подію fsw. + до того, працюючи над низкою програм, які зазнали помилок fsw.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.