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:/
Today i crashed in FileSystemWatcher and found this site. Suggested Thread.Sleep cannot completely eliminate problem. Tested with fast counter-integer. And is blocking UI. Most problematic is startup, it sliped trough at 5s. Then i set FileSystemWatcher1.EnableRaisingEvents = False immediately in TimerWatcherChanged.Tick and never enabled again... But surprisingly counter still catch up-to 4 events! I would like to share my solution, non-blocking, with adjustable Timer. Feedback is welcome.
Imports System.IO
Imports System.Diagnostics
Public Class Form1
Dim fileName As String
Dim Fsw_counter As Integer
WithEvents TimerWatcherChanged As New Windows.Forms.Timer
WithEvents TimerTest As New Windows.Forms.Timer
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
TimerWatcherChanged.Interval = 100
TimerTest.Interval = 100 : TimerTest.Start()
TextBox1.Text = "C:\Downloads\New Text Document.txt"
TextBox1.SelectionStart = TextBox1.Text.Length
WatcherSetup()
End Sub
Sub WatcherSetup()
fileName = TextBox1.Text
FileSystemWatcher1.IncludeSubdirectories = False
FileSystemWatcher1.Path = Path.GetDirectoryName(fileName)
FileSystemWatcher1.Filter = Path.GetFileName(fileName)
FileSystemWatcher1.NotifyFilter = NotifyFilters.LastWrite
FileSystemWatcher1.EnableRaisingEvents = True
End Sub
Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
WatcherSetup()
End Sub
Private Sub FileSystemWatcher1_Changed(sender As Object, e As FileSystemEventArgs) Handles FileSystemWatcher1.Changed
If TimerWatcherChanged.Enabled = False Then
TimerWatcherChanged.Enabled = True
Fsw_counter += 1
' ***** Your WATCH Code put here... *****
End If
End Sub
Private Sub TimerWatcherChanged_Tick(sender As Object, e As EventArgs) Handles TimerWatcherChanged.Tick
TimerWatcherChanged.Enabled = False
End Sub
Private Sub TimerTest_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles TimerTest.Tick
TextBox2.Text = "Changed: " & Fsw_counter
If TimerWatcherChanged.Enabled = True Then
TextBox2.BackColor = Color.Red
Else
TextBox2.BackColor = Color.LawnGreen
End If
End Sub
End Class
Check e.ChangeType. I imagine you're getting two different notifications. Perhaps LastAccess and LastModified. In which case, that's the expected behavior.
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.