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

StackOverflow https://stackoverflow.com/questions/239988

Вопрос

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

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

Какие проблемы (производительность, надежность и т. д.) возникают при использовании любого из этих методов?

Это было полезно?

Решение

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

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

Другие советы

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

Вот статья MSDN о буфере: FileSystemWatcher .. ::. InternalBufferSize Property

По MSDN:

  

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

РЕДАКТИРОВАТЬ: точка зрения nmclean для обоснованности использования как ЖСБ, так и опросов (вы можете прочитать обсуждение в комментариях, если вам интересно) представляется весьма рациональным объяснением того, почему быть ситуации, когда использование как FSW, так и опроса является эффективным. Спасибо, что пролили свет на это для меня (и всех, кто придерживается того же мнения), nmclean .

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

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

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

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

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, так как гораздо проще смоделировать / заглушить наличие файлов или иным образом при запуске события опроса, чем полагаться на более " неконтролируемый " FSS событие. + к тому, что он работал над несколькими приложениями, которые страдали от ошибок fsw.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top