Вопрос по vb.net, visual-studio-2010, filesystemwatcher – Почему FileSystemWatcher запускается дважды

8

почему 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
Я придумал рабочее исправление. Пожалуйста, попробуйте. Arrow
возможный дубликатFileSystemWatcher Измененное событие возникает дважды Neolisk
FSW имеет очень низкоуровневое представление о файловой системе. Естьдва объекты файловой системы, связанные с файлом. Файл и запись каталога для файла. Они оба меняются. Это н'В противном случае сильно отличается от какой-либо программы, быстро меняющей файл. Hans Passant
Вы также должны избавиться от точки с запятой послеMessageBox оповещения. Arrow

Ваш Ответ

3   ответа
1

ия. Возможно LastAccess и LastModified. В этом случае этоожидаемое поведение.

спасибо, но если я возьму их, то все равно срабатывает дважды Hello-World
0

тема. Спящий не может полностью устранить проблему. Проверено с быстрым встречным числом. И блокирует пользовательский интерфейс. Наиболее проблематичным является запуск, он проскальзывает через 5 с. Затем я устанавливаю FileSystemWatcher1.EnableRaisingEvents = False сразу в TimerWatcherChanged.Tick и больше никогда не включается ... Но, что удивительно, счетчик по-прежнему перехватывает до 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
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

Это решение, хотя немногоHacky, работает. Он отключает проверку новых изменений / событий на 250 мс, а затем повторно включает проверку, исходя из предположения, что вы выиграли »не нужно проверять изменения каждые 250 мс. Я перепробовал почти все, что мог придумать, чтобы найти для вас реальное решение, но пока что это сработает.

Спасибо, первая техника сработала для меня. Я использовалFileSystemWatcher в небольшом сервисе Windows, который компилировал таблицы стилей для использования LiveReload, и события множественных изменений затопляли браузер. Но эта маленькая корректировка исправилаFUOCпроблема ;) harpo
Спасибо. Я только что нашел более подходящее, работоспособное решение, которое очень похоже, хотя и не требует использования потоков. Обновляю сейчас. Arrow
Я уже видел этот тип решения, использовавшийся ранее и в других публикациях в Интернете. Это хорошо сработало и для меня. Microsoft объясняет это наmsdn.microsoft.com/en-us/library/... JimDel

Похожие вопросы