8

为什么 FileSystemWatcher 会触发两次?有没有简单的方法来修复它?当然,如果我更新或编辑文本文件,它应该只触发一次?

这个链接在这里http://weblogs.asp.net/ashben/archive/2003/10/14/31773.aspx

  1. 引发两次的事件 - 如果显式指定事件处理程序(AddHander FSW.Created、AddressOf FSW_Created),则将引发两次事件。这是因为默认情况下,公共事件会自动调用相应的受保护方法(OnChanged、OnCreated、OnDeleted、OnRenamed)。要纠正此问题,只需删除显式事件处理程序 (AddHandler ...)。

“删除显式事件处理程序”是什么意思?

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
4

3 回答 3

8

更新:

我想出了2个解决方案。一个使用线程,另一个不使用。选择你的:-)。

没有线程:

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

此解决方案(无线程)将 watcher.EnableRaisingEvents 设置为 False。在此之后,您通常会处理受影响(或更改)的任何文件。然后在您完成工作后将 EnableRaisingEvents 设置回 True。

使用线程:

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

这个解决方案虽然有点老套,但确实有效。它会在 250 毫秒内禁用检查新更改/事件,然后重新启用检查,前提是您不需要每 250 毫秒检查一次更改。我已经尝试了几乎所有我能想到的为您找到真正解决方案的方法,但这同时也会奏效。

于 2012-10-17T18:20:07.617 回答
1

检查 e.ChangeType。我想你会收到两个不同的通知。也许是 LastAccess 和 LastModified。在这种情况下,这是预期的行为。

于 2012-10-17T18:19:17.580 回答
0

今天我在 FileSystemWatcher 中崩溃并找到了这个站点。建议的 Thread.Sleep 不能完全消除问题。用快速反整数测试。并且正在阻止用户界面。最有问题的是启动,它在 5 秒时滑入低谷。然后我立即在 TimerWatcherChanged.Tick 中设置 FileSystemWatcher1.EnableRaisingEvents = False 并且再也没有启用......但令人惊讶的是,计数器仍然可以捕获多达 4 个事件!我想与可调定时器分享我的解决方案,非阻塞。欢迎反馈。

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
于 2018-05-01T18:06:51.467 回答