Почему FileSystemWatcher срабатывает дважды
Почему FileSystemWatcher срабатывает дважды? Есть ли простой способ исправить это? Конечно, если я обновлю или отредактирую текстовый файл, он должен сработать только один раз?
Эта ссылка здесь http://weblogs.asp.net/ashben/archive/2003/10/14/31773.aspx говорит
- события, вызываемые дважды-событие будет вызываться дважды, если обработчик событий (AddHander FSW.Создано, 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:UserscDesktoptest"
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
3 ответа:
Обновление:
Я придумал 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
Это решение (без резьбы) устанавливает наблюдатель.EnableRaisingEvents к ложному. Именно после этого момента вы обычно обрабатываете все файлы, которые были затронуты (или изменены). Затем он устанавливает 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 мс. я перепробовал почти все, что мог придумать, чтобы получить реальное решение для вас, но это будет работать в то же время.
Проверьте e.тип изменения. Я думаю, вы получаете два разных уведомления. Возможно, LastAccess и LastModified. В таком случае, это ожидаемое поведение.
Сегодня я врезался в FileSystemWatcher и нашел этот сайт. Предложил Нить.Сон не может полностью устранить проблему. Тестировался с быстрым целочисленным счетчиком. И блокирует пользовательский интерфейс. Наиболее проблематичным является автозагрузки, она проскальзывала Через на 5s. Тогда я поставил FileSystemWatcher1.EnableRaisingEvents = False немедленно в TimerWatcherChanged.Поставьте галочку и больше никогда не включайте... Но на удивление счетчик все-таки догнал-до 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