Paul
Paul

Reputation: 777

FileSystemWatcher stops catching events

I am writing a c# program to let me know when a file has been added or deleted. I run it on my Windows 7 machine and watch an FTP server on our network.

It works fine but will suddenly stop catching any events. I'm guessing that it might be losing connection to the server or there is a glitch in the network.

How can I handle this situation in the code. Is there some exception I can watch for and try to restart the FileSystemWatcher object.

Any suggestions and code samples would be appreciated.

Upvotes: 25

Views: 28321

Answers (4)

Jaap Ettema
Jaap Ettema

Reputation: 1

I solved this problem by raising the:

(name of FileSystemWatcher).InternalBufferSize = MyInternalBufferSize
Read(FileSystemWatcher.InternalBufferSize Property)

(Documentation)

I tested it with an InternalBufferSize at max 64 KB and placed 320 dummy files in the FileSystemWatcher path and it ran like Speedy Gonzales.

Upvotes: -1

Tomer Salem
Tomer Salem

Reputation: 34

You can create a method that initiates the FileSystemWatcher, and in case of an error, just restart it.

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

Upvotes: 0

Rene
Rene

Reputation: 302

The previous answer does not fix it completely, I had to reset the watcher not just turn it on and off. I use filesystemwatcher on a window service

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

Upvotes: 17

Paul
Paul

Reputation: 777

I needed to add an error handler for the FileSystemWatcher

fileSystemWatcher.Error += new ErrorEventHandler(OnError);

And then add this code:

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

Here is how I reset the SystemFileWatcher object:

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

    }

I think this code should do what I want it to do.

Upvotes: 24

Related Questions