views:

81

answers:

3

Ok, so I learnt from How to check if a open file has been updated that I should use a FileSystemWatcher to watch for changes to files. Then now, the question is if I must keep track of many files, do I create 1 watcher for each file? Also, I must somehow dispose of the watcher once the file is closed. Is having a Dictionary<string, FileSystemWatcher> storing the filepath and the FileSystemWatcher the way to go? as I open more files, I add more watcher and as I close, dispose of the watchers appropriately. Will having too many watchers be a bad thing?

UPDATE

I just did

protected void AttachFileMonitor(EditorTabViewModel tab)
{
    string file = tab.FilePath;
    if (!_fsWatchers.ContainsKey(file))
    {
        var watcher = new FileSystemWatcher();
        watcher.Path = Path.GetDirectoryName(file);
        watcher.Filter = Path.GetFileName(file);
        watcher.Changed += (s, e) =>
        {
            string message = "";
            string caption = "";
            MessageBoxButton buttons = MessageBoxButton.YesNo;
            MessageBoxImage image = MessageBoxImage.Question;
            MessageBoxResult defaultResult = MessageBoxResult.Yes;
            MessageBoxResult result = _dialogSvc.GetMessageBox(message, caption, buttons, image, defaultResult);
            if (result == MessageBoxResult.Yes)
            {
                tab.Open(file);
            }
        };
        _fsWatchers.Add(file, watcher);
    }
}
protected void DetachFileMonitor(EditorTabViewModel tab)
{
    if (_fsWatchers.ContainsKey(tab.FilePath)) {
        _fsWatchers.Remove(tab.FilePath);
    }
}

I found that Changed() never gets triggered ...

+2  A: 

It's enough if you create a watcher for each directory (and optionally, you can have the watcher to monitor a whole directory tree.) You can then use the events to compare the changed files with the list of files you are interested in.

I would suggest you make some kind of "nanny" class for the watchers to ensure you doesn't dispose active watchers, or create duplicate. Just a tip :)

Btw, yes, there's a limit, you can't create infinite watchers. In specific scenarios that can be a problem, but most likely, that's not the case for you

Onkelborg
I wonder if I am doing anything wrong? `FileSystemWatcher` seems to not work for me. or is that why so many people warn against using it?
jiewmeng
I'm guessing, but have you set EnableRaisingEvents to true?
Onkelborg
That worked, but changed gets raised 2 times even when I save from my app. I read that this might happen but how can I check if the event has been raised b4 already?
jiewmeng
That sounds a bit strange, but an easy solution is to get the LastWriteTime for the file, save it, and then compare in the eventhandler. If change: ask, if no change: ignore
Onkelborg
+1  A: 

I think you're definitely on the right track. It's up to you how to store the multiple fileWatchers but disposing of them and clearing their queue as quickly as possible are important for reliability. You only need one per directory, not file.

There are lots of posts about the unreliability of fileWatchers so be diligent in your usage.

ach
I wonder if I am doing anything wrong? `FileSystemWatcher` seems to not work for me. or is that why so many people warn against using it?
jiewmeng
A: 

This really is a trade-off. Many watchers will consume more resources, but if you have a watcher on a directory containing many files/sub directories (e.g. C:), this will also consume a lot of resources.

If all the files are located in a single folder, you should just use the single watcher.

Pieter
There's one more thing to consider: a watcher will consume resources, yes, but it won't be polling, and polling is in most cases evil. It's mostly better to be idle and wait for something instead of actively ask for something. In terms of performance and responsiveness it's clearly preferred to wait instead of ask.
Onkelborg
No, it won't be polling. However, it will receive every change within the folder structure you've specified. Specifically when you specify C:\, you will get notified of all activity on you C:\ drive, and this will be a lot.
Pieter
Yes, I know it wont be polling, I was talking about the alternative to using a FileSystemWatcher: polling ;) But if you specfiy C:\ there wont be much activity, not unless you enable recursive mode. The point I was trying to make is that it's likely that polling uses more resources than a watcher.
Onkelborg
Ah, yes, absolutely.
Pieter