FileSystemWatcher Changed event is raised twice

前端 未结 30 3270
死守一世寂寞
死守一世寂寞 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:11

    I had to combine several ideas from the posts above and add file locking check to get it working for me:

    FileSystemWatcher fileSystemWatcher;
    
    private void DirectoryWatcher_Start()
    {
        FileSystemWatcher fileSystemWatcher = new FileSystemWatcher
        {
            Path = @"c:\mypath",
            NotifyFilter = NotifyFilters.LastWrite,
            Filter = "*.*",
            EnableRaisingEvents = true
        };
    
        fileSystemWatcher.Changed += new FileSystemEventHandler(DirectoryWatcher_OnChanged);
    }
    
    private static void WaitUntilFileIsUnlocked(String fullPath, Action callback, FileAccess fileAccess = FileAccess.Read, Int32 timeoutMS = 10000)
    {
        Int32 waitMS = 250;
        Int32 currentMS = 0;
        FileInfo file = new FileInfo(fullPath);
        FileStream stream = null;
        do
        {
            try
            {
                stream = file.Open(FileMode.Open, fileAccess, FileShare.None);
                stream.Close();
                callback(fullPath);
                return;
            }
            catch (IOException)
            {
            }
            finally
            {
                if (stream != null)
                    stream.Dispose();
            }
            Thread.Sleep(waitMS);
            currentMS += waitMS;
        } while (currentMS < timeoutMS);
    }    
    
    private static Dictionary DirectoryWatcher_fileLastWriteTimeCache = new Dictionary();
    
    private void DirectoryWatcher_OnChanged(Object source, FileSystemEventArgs ev)
    {
        try
        {
            lock (DirectoryWatcher_fileLastWriteTimeCache)
            {
                DateTime lastWriteTime = File.GetLastWriteTime(ev.FullPath);
                if (DirectoryWatcher_fileLastWriteTimeCache.ContainsKey(ev.FullPath))
                {
                    if (DirectoryWatcher_fileLastWriteTimeCache[ev.FullPath].AddMilliseconds(500) >= lastWriteTime)
                        return;     // file was already handled
                }
    
                DirectoryWatcher_fileLastWriteTimeCache[ev.FullPath] = lastWriteTime;
            }
    
            Task.Run(() => WaitUntilFileIsUnlocked(ev.FullPath, fullPath =>
            {
                // do the job with fullPath...
            }));
    
        }
        catch (Exception e)
        {
            // handle exception
        }
    }
    

提交回复
热议问题