Why does FileSystemWatcher fire twice

前端 未结 3 771
温柔的废话
温柔的废话 2021-01-12 06:00

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:/

相关标签:
3条回答
  • 2021-01-12 06:30

    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
    
    0 讨论(0)
  • 2021-01-12 06:41

    Check e.ChangeType. I imagine you're getting two different notifications. Perhaps LastAccess and LastModified. In which case, that's the expected behavior.

    0 讨论(0)
  • 2021-01-12 06:42

    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.

    0 讨论(0)
提交回复
热议问题