FileSystemWatcher Changed event is raised twice

前端 未结 30 3871
死守一世寂寞
死守一世寂寞 2020-11-22 06:01

I have an application where I am looking for a text file and if there are any changes made to the file I am using the OnChanged eventhandler to handle the event

30条回答
  •  青春惊慌失措
    2020-11-22 06:24

    Event if not asked, it is a shame there are no ready solution samples for F#. To fix this here is my recipe, just because I can and F# is a wonderful .NET language.

    Duplicated events are filtered out using FSharp.Control.Reactive package, which is just a F# wrapper for reactive extensions. All that can be targeted to full framework or netstandard2.0:

    let createWatcher path filter () =
        new FileSystemWatcher(
            Path = path,
            Filter = filter,
            EnableRaisingEvents = true,
            SynchronizingObject = null // not needed for console applications
        )
    
    let createSources (fsWatcher: FileSystemWatcher) =
        // use here needed events only. 
        // convert `Error` and `Renamed` events to be merded
        [| fsWatcher.Changed :> IObservable<_>
           fsWatcher.Deleted :> IObservable<_>
           fsWatcher.Created :> IObservable<_>
           //fsWatcher.Renamed |> Observable.map renamedToNeeded
           //fsWatcher.Error   |> Observable.map errorToNeeded
        |] |> Observable.mergeArray
    
    let handle (e: FileSystemEventArgs) =
        printfn "handle %A event '%s' '%s' " e.ChangeType e.Name e.FullPath 
    
    let watch path filter throttleTime =
        // disposes watcher if observer subscription is disposed
        Observable.using (createWatcher path filter) createSources
        // filter out multiple equal events
        |> Observable.distinctUntilChanged
        // filter out multiple Changed
        |> Observable.throttle throttleTime
        |> Observable.subscribe handle
    
    []
    let main _args =
        let path = @"C:\Temp\WatchDir"
        let filter = "*.zip"
        let throttleTime = TimeSpan.FromSeconds 10.
        use _subscription = watch path filter throttleTime
        System.Console.ReadKey() |> ignore
        0 // return an integer exit code
    

提交回复
热议问题