SystemFileWatcher不会触发事件

时间:2019-03-20 20:02:09

标签: c# .net file

我一直在试图理解为什么我的FSW不触发任何事件。我在Application_Start中实例化了我的以下类的新对象,并执行了WatchFile()但没有任何反应=(

public class FileWatcherClass
    {
        private FileSystemWatcher _watcher;
        public void WatchFile(string fileName, string directory)
        {
            // Create a new FileSystemWatcher and set its properties.
            using (_watcher = new FileSystemWatcher(directory, "*.xml"))
            {
                _watcher.NotifyFilter = NotifyFilters.Attributes |
                                        NotifyFilters.CreationTime |
                                        NotifyFilters.FileName |
                                        NotifyFilters.LastAccess |
                                        NotifyFilters.LastWrite |
                                        NotifyFilters.Size |
                                        NotifyFilters.Security;

                // Add event handlers.
                _watcher.Changed +=
                new FileSystemEventHandler(OnChanged);

                // Begin watching.
                _watcher.EnableRaisingEvents = true;

            }
        }

        // Define the event handlers.
        public void OnChanged(object source, FileSystemEventArgs e) { 
            do something..
        }
    }

2 个答案:

答案 0 :(得分:5)

问题与您使用using语句有关:

using (_watcher = new FileSystemWatcher(directory, "*.xml"))

当执行到达using块的末尾时,将放置观察程序,这意味着它无法再引发事件。

删除用于解决问题的方法:

_watcher = new FileSystemWatcher(directory, "*.xml");

但是,这带来了另一个问题,那就是从不部署观察者。一种方法是在IDisposable上实现FileWatcherClass,然后根据需要配置观察者:

public void Dispose()
{
    _watcher?.Dispose(); // if _watcher isn't null, dispose it
}

然后,您只需在处理完FileWatcherClass实例后就可以对其进行处置。

答案 1 :(得分:0)

这里的实现稍微灵活一些。

用法

    static void Main(string[] args)
    {
        using (var watcherManager= new FileSystemWatcherManager())
        {
            watcherManager.OnChangedDetected += (a) =>
            {
                // General event
            };

            watcherManager.RegisterWatcher(@"C:\temp\helloworld");
            watcherManager.RegisterWatcher(@"C:\temp\api-demo", customChangeEvent: (s, e) =>
            {
                // Handle change directly
            });

            Console.ReadKey();
        };
   }

实施

public sealed class FileSystemWatcherManager : IDisposable
{
    private bool _disposed = false;
    private readonly Dictionary<string, FileSystemWatcher> _watchers;
    public delegate void ChangedDetected(FileSystemEventArgs args);
    public event ChangedDetected OnChangedDetected;

    public FileSystemWatcherManager()
    {
        _watchers = new Dictionary<string, FileSystemWatcher>();
    }

    ~FileSystemWatcherManager()
    {
        Dispose(false);
    }

    public FileSystemWatcher RegisterWatcher(string directoryPath, string filter = "*", FileSystemEventHandler customChangeEvent = null)
    {
        if (Directory.Exists(directoryPath))
        {
            if (!_watchers.ContainsKey(directoryPath))
            {
                var watcher = new FileSystemWatcher(directoryPath, filter)
                {
                    EnableRaisingEvents = true,
                    IncludeSubdirectories = true
                };
                watcher.NotifyFilter =  NotifyFilters.Attributes |
                                        NotifyFilters.CreationTime |
                                        NotifyFilters.FileName |
                                        NotifyFilters.LastAccess |
                                        NotifyFilters.LastWrite |
                                        NotifyFilters.Size |
                                        NotifyFilters.Security;

                if (customChangeEvent != null)
                    watcher.Changed += customChangeEvent;
                else
                    watcher.Changed += Watcher_Changed;

                _watchers.Add(directoryPath, watcher);
            }
        }
        else
        {
            throw new InvalidOperationException($"Invalid Directory: {directoryPath}");
        }

        return _watchers.TryGetValue(directoryPath, out FileSystemWatcher value) ? value : null;
    }

    private void Watcher_Changed(object sender, FileSystemEventArgs e)
    {
        OnChangedDetected?.Invoke(e);
    }

    public void Dispose()
    {
        Dispose(true);

        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
        if (_disposed)
        {
            if (disposing)
            {
                foreach(KeyValuePair<string,FileSystemWatcher> pair in _watchers)
                {
                    pair.Value.Dispose();                       
                }

                _watchers.Clear();
            }

            _disposed = true;
        }
    }
}