Класса filesystemwatcher против избирательных, чтобы наблюдать за изменениями файла


Мне нужно настроить приложение, которое следит за файлами, создаваемыми в каталоге, как локально, так и на сетевом диске.

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

какие проблемы (производительность, надежность и т. д.) есть ли какой-либо метод?

13 135

13 ответов:

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

Edit: если у вас есть пользовательский интерфейс, вы также можете дать пользователю возможность "обновить" изменения вместо опроса. Я бы объединил это с наблюдателем файловой системы.

самая большая проблема, с которой я столкнулся, - это отсутствие файлов, когда буфер заполняется. Легко исправить-просто увеличить буфер. Помните, что он содержит имена файлов и события, поэтому увеличьте его до ожидаемого количества файлов (проб и ошибок). Он использует память, которая не может быть выгружена, поэтому он может заставить другие процессы на страницу, если память становится низкой.

вот статья MSDN о буфере : FileSystemWatcher..::.InternalBufferSize Собственность

Per MSDN:

увеличение размера буфера дорого, так как он поступает из нестраничной памяти, которая не может быть заменена на диск, поэтому держите буфер как можно меньше. Чтобы избежать переполнения буфера, используйте свойства NotifyFilter и IncludeSubdirectories для фильтрации нежелательных уведомлений об изменениях.

мы используем 16 МБ из-за большой партии, ожидаемой в одно время. Отлично работает и никогда не пропускает файл.

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

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

на FileSystemWatcher может также пропустить изменения во время занятости, если количество изменений в очереди переполняет предоставленный буфер. Это не ограничение класса .NET как такового, а базовой инфраструктуры Win32. По нашему опыту, лучший способ минимизировать эту проблему-как можно быстрее удалить уведомления из очереди и разобраться с ними в другом потоке.

Как упоминалось выше @ChillTemp, наблюдатель может не работать на общих ресурсах, отличных от Windows. Например, это не будет работа вообще на монтируемых приводах Novell.

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

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

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

В настоящее время я использую FileSystemWatcher в XML-файл обновляется в среднем каждые 100 миллисекунд.

Я нашел, что до тех пор, как FileSystemWatcher правильно настроен вы никогда не должны иметь проблем с местные файлы.

у меня нет опыта в удаленном просмотре файлов и не-Windows shares.

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

Я бы пошел с опросом.

сетевые проблемы вызывают FileSystemWatcher быть ненадежным (даже при перегрузке события ошибки).

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

У меня были некоторые большие проблемы с FSW на сетевых дисках: удаление файла всегда вызывало событие ошибки, а не удаленное событие. Я не нашел решения, поэтому теперь я избегаю FSW и использую опрос.

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

кроме того, у меня не было никаких проблем с локальными папками, независимо от того, разделяют или нет.

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

в настоящее время я пытаюсь решить, буду ли я использовать FSW или опрос для проекта, который я разрабатываю. Читая ответы, очевидно, что есть случаи, когда FSW покрывает потребности прекрасно, в то время как в других случаях, вы нужно опрос. К сожалению, нет ответа на самом деле имел дело с производительность разница (если есть), только с вопросами "надежности". Может кто-то ответить на эту часть вопроса?

EDIT : nmcleanточка для обоснованности использования как FSW, так и опроса(вы можете прочитать обсуждение в комментариях, если вам интересно) кажется очень рациональной объяснение, почему могут быть ситуации, которые используют как FSW, так и опрос и эффективным. Спасибо, что пролили свет на это для меня (и любого другого, имеющего такое же мнение),nmclean.

рабочее решение для работы с create event вместо change

даже для копирования, вырезать, вставить, переместить.

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;
    }
}

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

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

возвращение из метода события как можно быстрее, используя другой поток, решило проблему для меня:

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