Search code examples
vb.netvisual-studio-2010filesystemwatcher

Why does FileSystemWatcher fire twice


why does the FileSystemWatcher fire twice? Is there an easy way to fix it? Surely if I update or edit the text file it should only fire once?

this link here http://weblogs.asp.net/ashben/archive/2003/10/14/31773.aspx says

  1. Events being raised twice - An event will be raised twice if an event handler (AddHander FSW.Created, AddressOf FSW_Created) is explicitly specified. This is because, by default, the public events automatically call the respective protected methods (OnChanged, OnCreated, OnDeleted, OnRenamed). To correct this problem, simply remove the explicit event handler (AddHandler ...).

What does "remove the explicit event handler" mean?

Imports System.IO

Public Class Form2

    Private Sub FileSystemWatcher1_Changed(ByVal sender As System.Object, ByVal e As System.IO.FileSystemEventArgs) Handles FileSystemWatcher1.Changed

        'this fires twice
        MessageBox.Show("test")

    End Sub

    Private Sub Form2_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        FileSystemWatcher1.Path = "C:\Users\c\Desktop\test\"
        FileSystemWatcher1.NotifyFilter = NotifyFilters.LastAccess Or NotifyFilters.LastWrite Or NotifyFilters.FileName Or NotifyFilters.DirectoryName Or NotifyFilters.CreationTime

        FileSystemWatcher1.IncludeSubdirectories = False
        FileSystemWatcher1.Filter = "text.txt"

    End Sub

End Class

Solution

  • Update:

    I have come up with 2 solutions. One uses Threads, and the other doesn't. Take your pick :-).

    Without threading:

    Imports System.IO
    
    Public Class Form1
        Private Sub FileSystemWatcher1_Changed(ByVal sender As System.Object, ByVal e As System.IO.FileSystemEventArgs) Handles FileSystemWatcher1.Changed
            Dim watcher As System.IO.FileSystemWatcher = sender
            watcher.EnableRaisingEvents = False
    
            'Do work here while new events are not being raised.
            MessageBox.Show("Test")
    
            watcher.EnableRaisingEvents = True 'Now we can begin watching for new events.
    
        End Sub
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    
            FileSystemWatcher1.Path = "C:\Users\c\Desktop\test"
            FileSystemWatcher1.NotifyFilter = NotifyFilters.LastWrite
            FileSystemWatcher1.IncludeSubdirectories = False
            FileSystemWatcher1.Filter = "test.txt"
    
    
        End Sub
    
        Private Sub FileSystemWatcher_OnChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
    
        End Sub
    
    End Class
    

    This solution (without threading), sets the watcher.EnableRaisingEvents to False. It is after this point where you would normally process whatever files are affected (or changed). It then sets the EnableRaisingEvents back to True after your work is done.

    With threading:

    Imports System.IO
    
    Public Class Form1
        Private Sub FileSystemWatcher1_Changed(ByVal sender As System.Object, ByVal e As System.IO.FileSystemEventArgs) Handles FileSystemWatcher1.Changed
            FileSystemWatcher1.EnableRaisingEvents = False
            Threading.Thread.Sleep(250)
            FileSystemWatcher1.EnableRaisingEvents = True
    
    
            MessageBox.Show("test")
    
    
        End Sub
    
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    
            FileSystemWatcher1.Path = "C:\Users\c\Desktop\test"
            FileSystemWatcher1.NotifyFilter = NotifyFilters.LastWrite
            FileSystemWatcher1.IncludeSubdirectories = False
            FileSystemWatcher1.Filter = "test.txt"
    
    
        End Sub
    
        Private Sub FileSystemWatcher_OnChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
    
        End Sub
    
    End Class
    

    This solution, although a bit hacky, does work. It disables checking for new changes/events for 250ms and then re-enables checking, based on the assumption that you won't been needing to check for a change every 250ms. I have tried almost everything that I could think of to get a real solution for you but this will work in the meantime.