C# - Predict file system events on folder delete

前端 未结 3 528
礼貌的吻别
礼貌的吻别 2021-01-18 17:37

This is more a question about what\'s the best practice in implementing this.

I have a FileSystemWatcher which should inform me about User\'s changes on

相关标签:
3条回答
  • 2021-01-18 18:04

    Ok here is my solution of the problem:

    Just for delete command:

    I implemented 2 lists, one for file deletes and one for folder deletes.

    file list entrys have no timeout. If I delete a file I create a list entry and if I get the expected delete event I remove the entry as before.

    folder list entrys have no timeout after create. I can command them manually to time out after a second by a special method. If I delete a folder I add a deleteFolder list entry. Every delete event from this folder or file or subfolder or subfolderfile is ignored because of this delete folder entry. After the delete is finished I arm the timeout for the deleteFolder entry. If the delete throws an exception I do the same. So I expect to get all events after a second. So I'm ignoring all events if the delete command works or not. After this the deleteFolder list entry gets deleted.

    Limitations: 1. all delete events have to come in one second after the delete happened. 2. it is not allowed to delete a folder like this:
    delete folder (completed)
    create folder again
    wait less then 1 second
    delete folder again (timeout has not finished of the delete folder list entry)

    Hope this helps somebody even it is very complicated ^^

    0 讨论(0)
  • 2021-01-18 18:09

    I've done exactly this sort of thing recently; the trick is to have your 'list' recognise that where there's a folder name in the list, also discard any events for anything within that folder if it's expecting a delete event, and only remove it from your prediction list if it's the folder itself.

    I should warn you though, you're likely to encounter problems with the FileSystemWatchers buffer becoming full if too many events happen in rapid succession; if this does, it'll fire an Error event, and fail to notify you of a whole bunch of events. If your prediction list removes items as it receives the event, you run the risk of ignoring future events just because the event you intended to ignore was never received due to a buffer overflow. It may also get very large, as items are never being removed from the list.

    I've yet to find a reliably way of doing this, although you can set the size of the FileSystemWatchers buffer to maximum to mitigate it to a degree.

    EDIT: Also very important: The events that come back do so on a different thread (unless your handler is on an object that implements ISynchronizeInvoke, such as a Control or Form, and you set the SynchronizingObject to your Control/Form. This means you need to be very careful how you maintain your list, taking into account potential race conditions. I'm still struggling with this one; my code flushes the prediction list on receiving an error event, but by the time it handles the event, other change events since the error have already been fired and handled, and it flushes things it shouldn't.

    0 讨论(0)
  • 2021-01-18 18:24

    Regarding the buffer overflow. The best way to solve it is to do the work in response to an event on another thread. I do it like this

    // Queue of changed paths.
    private readonly Queue<string> mEventQueue = new Queue<string>();
    
    // add this as handler for filesystemwatcher events
    public void FileSystemEvent(object source, FileSystemEventArgs e) {
        lock (mEventQueue) {
            if (!mEventQueue.Contains(e.FullPath)) {
                mEventQueue.Enqueue(e.FullPath);
                Monitor.Pulse(mEventQueue);
            }
        }
    }
    
    // start this on another thread
    public void WatchLoop() {
        string path;
        while (true) {
            lock (mEventQueue) {
                while (mEventQueue.Count == 0)
                    Monitor.Wait(mEventQueue);
                path = mEventQueue.Dequeue();
                if (path == null)
                   break;
            }
            // do whatever you want to do
         }
    }
    

    That way I will never miss an event

    0 讨论(0)
提交回复
热议问题