FileSystemWatcher перестает ловить события

Я пишу программу на C #, чтобы сообщать мне, когда файл был добавлен или удален. Я запускаю его на своей машине с Windows 7 и смотрю FTP-сервер в нашей сети.

Он работает нормально, но внезапно перестанет ловить какие-либо события. Я предполагаю, что это может быть потеря связи с сервером или сбой в сети.

Как я могу справиться с этой ситуацией в коде. Есть ли какое-то исключение, за которым я могу наблюдать и пытаться перезапустить объект FileSystemWatcher.

Будем признательны за любые предложения и образцы кода.


person Paul    schedule 31.05.2011    source источник
comment
Итак, если был загружен 1 КБ файла, как узнать, что передача завершена? Я думаю, вам нужно переосмыслить здесь свой подход.   -  person leppie    schedule 31.05.2011
comment
Ознакомьтесь с этим вопросом об исключениях при чтении созданных файлов с помощью FileSystemWatcher stackoverflow.com/questions/699538/   -  person Oskar Kjellin    schedule 31.05.2011
comment
Он отлично работает для захвата, когда файлы создаются или удаляются. Мне просто нужно знать, как восстановить потерянное соединение или сбой сети. Возникает ли какой-либо тип исключения для объекта FileSystemWatcher?   -  person Paul    schedule 01.06.2011
comment
Думаю, теперь я знаю, что мне нужно делать. Перехватите исключение, которое генерирует fileSystemWatcher, а затем попробуйте повторно включить для него создание событий, когда сервер снова станет доступным. Я не понимаю, куда бы я поставил попытку / уловить.   -  person Paul    schedule 01.06.2011


Ответы (3)


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

void NotAccessibleError(FileSystemWatcher source, ErrorEventArgs e)
{
    int iMaxAttempts = 120;
    int iTimeOut = 30000;
    int i = 0;
    while ((!Directory.Exists(source.Path) || source.EnableRaisingEvents == false) && i < iMaxAttempts)
    {
        i += 1;
        try
        {
            source.EnableRaisingEvents = false;
            if (!Directory.Exists(source.Path))
            {
                MyEventLog.WriteEntry("Directory Inaccessible " + source.Path + " at " + DateTime.Now.ToString("HH:mm:ss"));
                System.Threading.Thread.Sleep(iTimeOut);
            }
            else
            { 
                // ReInitialize the Component
                source.Dispose();
                source = null;
                source = new System.IO.FileSystemWatcher();
                ((System.ComponentModel.ISupportInitialize)(source)).BeginInit();
                source.EnableRaisingEvents = true;
                source.Filter = "*.tif";
                source.Path = @"\\server\dir";
                source.NotifyFilter = System.IO.NotifyFilters.FileName;
                source.Created += new System.IO.FileSystemEventHandler(fswCatchImages_Changed);
                source.Renamed += new System.IO.RenamedEventHandler(fswCatchImages_Renamed);
                source.Error += new ErrorEventHandler(OnError);
                ((System.ComponentModel.ISupportInitialize)(source)).EndInit();
                MyEventLog.WriteEntry("Try to Restart RaisingEvents Watcher at " + DateTime.Now.ToString("HH:mm:ss"));
            }
        }
        catch (Exception error)
        {
            MyEventLog.WriteEntry("Error trying Restart Service " + error.StackTrace + " at " + DateTime.Now.ToString("HH:mm:ss"));
            source.EnableRaisingEvents = false;
            System.Threading.Thread.Sleep(iTimeOut);
        }
    }
}
person Rene    schedule 11.10.2012
comment
это, кажется, продолжает цикл и воссоздавать наблюдатель файловой системы, даже если в какой-то момент это будет успешным. Разве в цикле успеха не должно быть перерыва? - person Matt; 20.04.2016
comment
@Matt Он должен прерваться: 1) путь существует (доступен) и б) EnableRaisingEvents == true. - person Andreas Reiff; 13.10.2017
comment
Это назначает новый FileSystemWatcher локальной переменной. У вызывающего по-прежнему есть ссылка на старый экземпляр, который теперь удален. - person StackOverthrow; 05.10.2020

Мне нужно было добавить обработчик ошибок для FileSystemWatcher

fileSystemWatcher.Error += new ErrorEventHandler(OnError);

А затем добавьте этот код:

private void OnError(object source, ErrorEventArgs e)
{
    if (e.GetException().GetType() == typeof(InternalBufferOverflowException))
    {
        txtResults.Text += "Error: File System Watcher internal buffer overflow at " + DateTime.Now + "\r\n";
    }
    else
    {
        txtResults.Text += "Error: Watched directory not accessible at " + DateTime.Now + "\r\n";
    }
    NotAccessibleError(fileSystemWatcher ,e);
}

Вот как я сбрасываю объект SystemFileWatcher:

   static void NotAccessibleError(FileSystemWatcher source, ErrorEventArgs e)
    {
        source.EnableRaisingEvents = false;
        int iMaxAttempts = 120;
        int iTimeOut = 30000;
        int i = 0;
        while (source.EnableRaisingEvents == false && i < iMaxAttempts)
        {
            i += 1;
            try
            {
                source.EnableRaisingEvents = true;
            }
            catch
            {
                source.EnableRaisingEvents = false;
                System.Threading.Thread.Sleep(iTimeOut);
            }
        }

    }

Я думаю, что этот код должен делать то, что я хочу.

person Community    schedule 02.06.2011
comment
Если это действительно решает проблему, вы должны отметить это как ответ. Чего это стоит, какое исключение было выброшено? - person Chris Shain; 02.06.2011
comment
Крис, на самом деле меня не беспокоит, что это за исключение. Я просто хочу убедиться, что объект FileSystemWatcher перезапущен. - person Paul; 02.06.2011

Вы можете создать метод, который запускает FileSystemWatcher, а в случае ошибки просто перезапустить его.

    private void WatchFile()
    {
        try
        {
            fsw = new FileSystemWatcher(path, filter)
            {
                EnableRaisingEvents = true
            };                
            fsw.Changed += Fsw_Changed;                
            fsw.Error += Fsw_Error;
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

    private void Fsw_Error(object sender, ErrorEventArgs e)
    {
        Thread.Sleep(1000);
        fsw.Changed -= Fsw_Changed;
        fsw.Error -= Fsw_Error;
        WatchFile();
    }
person Tomer Salem    schedule 05.12.2019
comment
Каждый раз, когда система выдает ошибку, вы создаете новый FileSystemWatcher. Я думаю, вы собираетесь исключить переполнение стека. - person Bastien Vandamme; 24.06.2021