为什么FileSystemWatcher会触发两次?有没有一种简单的方法来解决它?当然,如果我更新或编辑文本文件,它应该只触发一次?
此链接http://weblogs.asp.net/ashben/archive/2003/10/14/31773.aspx说
- 两次引发的事件 - 如果事件处理程序(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
答案 0 :(得分:8)
更新
我想出了两个解决方案。一个使用Threads,另一个不使用。请选择: - )。
没有线程:
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
这个解决方案虽然有点 hacky ,但确实有效。它会禁用检查250ms的新更改/事件,然后根据您不需要每250ms检查一次更改的假设重新启用检查。我已经尝试了几乎所有我能想到的东西来为你找到一个真正的解决方案,但这同时也适用。
答案 1 :(得分:1)
检查e.ChangeType。我想你会得到两个不同的通知。也许是LastAccess和LastModified。在这种情况下,这是预期的行为。
答案 2 :(得分:0)
今天我在FileSystemWatcher中崩溃并找到了这个网站。建议的Thread.Sleep不能完全消除问题。用快速反整数测试。并阻止UI。最有问题的是初创公司,它在5秒时跌幅低谷。然后我在TimerWatcherChanged.Tick中立即设置FileSystemWatcher1.EnableRaisingEvents = False并且再也没有启用...但令人惊讶的是,反击仍然可以赶上4个事件!我想与可调节的Timer共享我的解决方案,无阻塞。欢迎反馈。
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