Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FileSystemWatcher Changed event is raised twice

I have an application where I am looking for a text file and if there are any changes made to the file I am using the OnChanged eventhandler to handle the event. I am using the NotifyFilters.LastWriteTime but still the event is getting fired twice. Here is the code.

public void Initialize()
{
   FileSystemWatcher _fileWatcher = new FileSystemWatcher();
  _fileWatcher.Path = "C:\\Folder";
  _fileWatcher.NotifyFilter = NotifyFilters.LastWrite;
  _fileWatcher.Filter = "Version.txt";
  _fileWatcher.Changed += new FileSystemEventHandler(OnChanged);
  _fileWatcher.EnableRaisingEvents = true;
}

private void OnChanged(object source, FileSystemEventArgs e)
{
   .......
}

In my case the OnChanged is called twice, when I change the text file version.txt and save it.

like image 565
user214707 Avatar asked Nov 19 '09 16:11

user214707


People also ask

Is FileSystemWatcher reliable?

FileSystemWatcher is "known to be unreliable". In simple words, it doesn't work well. If the data size of the collected watcher events exceeds the size of the buffer created by FileSystemWatcher, the events that overflow are lost, and reliable exceptions are not raised.

What are the events associates with the FileSystemWatcher class?

Events. Occurs when a file or directory in the specified Path is changed. Occurs when a file or directory in the specified Path is created. Occurs when a file or directory in the specified Path is deleted.

Is FileSystemWatcher multithreaded?

Nope, filesystemwatchers run on their own thread.


4 Answers

I am afraid that this is a well-known bug/feature of the FileSystemWatcher class. This is from the documentation of the class:

You may notice in certain situations that a single creation event generates multiple Created events that are handled by your component. For example, if you use a FileSystemWatcher component to monitor the creation of new files in a directory, and then test it by using Notepad to create a file, you may see two Created events generated even though only a single file was created. This is because Notepad performs multiple file system actions during the writing process. Notepad writes to the disk in batches that create the content of the file and then the file attributes. Other applications may perform in the same manner. Because FileSystemWatcher monitors the operating system activities, all events that these applications fire will be picked up.

Now this bit of text is about the Created event, but the same thing applies to other file events as well. In some applications you might be able to get around this by using the NotifyFilter property, but my experience is says that sometimes you have to do some manual duplicate filtering (hacks) as well.

A while ago I bookedmarked a page with a few FileSystemWatcher tips. You might want to check it out.

like image 147
Jørn Schou-Rode Avatar answered Oct 08 '22 03:10

Jørn Schou-Rode


I've "fixed" that problem using the following strategy in my delegate:

// fsw_ is the FileSystemWatcher instance used by my application.

private void OnDirectoryChanged(...)
{
   try
   {
      fsw_.EnableRaisingEvents = false;

      /* do my stuff once asynchronously */
   }

   finally
   {
      fsw_.EnableRaisingEvents = true;
   }
}
like image 42
David Brabant Avatar answered Oct 08 '22 03:10

David Brabant


Any duplicated OnChanged events from the FileSystemWatcher can be detected and discarded by checking the File.GetLastWriteTime timestamp on the file in question. Like so:

DateTime lastRead = DateTime.MinValue;

void OnChanged(object source, FileSystemEventArgs a)
{
    DateTime lastWriteTime = File.GetLastWriteTime(uri);
    if (lastWriteTime != lastRead)
    {
        doStuff();
        lastRead = lastWriteTime;
    }
    // else discard the (duplicated) OnChanged event
}
like image 115
BaBu Avatar answered Oct 08 '22 03:10

BaBu


Here is my solution which helped me to stop the event being raised twice:

watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size;

Here I have set the NotifyFilter property with only Filename and size.
watcher is my object of FileSystemWatcher. Hope this will help.

like image 25
Deepashri Avatar answered Oct 08 '22 01:10

Deepashri