8

FileSystemWatcher が 2 回起動するのはなぜですか? それを修正する簡単な方法はありますか?テキストファイルを更新または編集すると、一度だけ起動するはずですか?

このリンクはこちらhttp://weblogs.asp.net/ashben/archive/2003/10/14/31773.aspxは言う

  1. 2 回発生するイベント - イベント ハンドラー (AddHander FSW.Created、AddressOf FSW_Created) が明示的に指定されている場合、イベントは 2 回発生します。これは、既定では、パブリック イベントがそれぞれの保護されたメソッド (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つの解決策を考え出しました。1 つはスレッドを使用し、もう 1 つは使用しません。好きなのを選びな :-)。

ねじ切りなし:

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 を確認します。2 つの異なる通知を受け取っていると思います。おそらく、LastAccess と LastModified です。その場合、それは予想される動作です。

于 2012-10-17T18:19:17.580 に答える
0

今日、私は FileSystemWatcher でクラッシュし、このサイトを見つけました。推奨される Thread.Sleep では、問題を完全に排除することはできません。高速カウンター整数でテスト済み。そしてUIをブロックしています。最も問題なのは起動で、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
于 2018-05-01T18:06:51.467 に答える