5

这更像是一个关于实现这一点的最佳实践的问题。

我有一个FileSystemWatcher应该通知我用户对文件和文件夹的更改。还监视子目录。在同一目录中,我的程序有时也会发生变化。我不想FileSystemWatcher检测这些程序更改的事件。

我的第一个实现是一个可以添加预期事件的列表。当我收到文件系统事件时,我会检查列表,如果存在则忽略它。这听起来不是很强大,但它似乎有效。

现在我发现了真正的问题:
D: 被FileSystemWatcher.
我有两个这样的文件夹: D:\folder1\folder2
现在我想用我的应用程序删除 folder1(其中包含 folder2)。所以我把 D:\folder1 放在我的删除列表中。然后我打电话给类似的东西Directory.Delete(@"D:\folder1", true)。现在我注意到 folder1 不能因为异常而被删除(为什么)。我从列表中删除了删除条目,但文件夹 2 已被删除,我得到了他的 FileSystemEvent。所以我得到了 D:\folder1\folder2 的 FileSystem 事件。我的程序认为现在用户已经删除了这个文件夹并且做错了事情。

我现在有一些想法:

1.)通过删除它自己的每个文件和每个文件夹来递归删除文件夹。有了这个,我得到每个子文件夹并归档一个自己的列表条目。我已经实现了它,但它非常非常非常慢。

2.)也许有更好的方法可以FileSystemWatcher让我的列表过时?

3.)如果可以删除所有内容,也许只能删除目录树。所以如果它失败了,我仍然拥有一切,如果不是,一切都被删除。这对我来说似乎是最优雅的解决方案,但不知道这是否可能?

4.) 是否可以通过我的软件独占锁定所有文件和文件夹?如果这一切正常,应该可以使用一个删除命令或类似的方式删除所有内容?

我也愿意接受其他额外的解决方案。

编辑 1 使其更清晰:

我只想“查看”文件夹上的用户操作。如果我在这里操作我的程序中的东西,我不想看到这些事件。

通过我的实现,如果文件夹被锁定并且无法删除,我会收到子文件夹的事件。

用英语解释并不容易,因为我不是英语母语人士;)。

编辑2:

5.) 也许可以FileSystemWatcher从定义的流程中过滤所有事件?

4

3 回答 3

2

我最近确实做过这种事情;诀窍是让您的“列表”识别列表中存在文件夹名称的位置,如果预期删除事件,也丢弃该文件夹中任何内容的任何事件,并且仅当它是文件夹本身时将其从预测列表中删除。

FileSystemWatcher不过我应该警告你,如果连续发生太多事件,你可能会遇到s 缓冲区变满的问题;如果这样做,它将触发一个Error事件,并且无法通知您一大堆事件。如果您的预测列表在收到事件时删除了项目,那么您将冒着忽略未来事件的风险,因为您打算忽略的事件由于缓冲区溢出而从未收到。它也可能变得非常大,因为项目永远不会从列表中删除。

我还没有找到一种可靠的方法来做到这一点,尽管您可以将FileSystemWatchers 缓冲区的大小设置为最大值以在一定程度上减轻它。

编辑:也非常重要:返回的事件在不同的线程上执行(除非您的处理程序位于实现的对象上ISynchronizeInvoke,例如 a Controlor Form,并且您将其设置SynchronizingObjectControl/ Form。这意味着您需要非常小心如何你维护你的列表,考虑到潜在的竞争条件。我仍然在努力解决这个问题;我的代码在接收到错误事件时刷新预测列表,但是当它处理事件时,由于错误已经发生了其他更改事件被解雇和处理,它冲洗不应该的东西。

于 2011-02-11T09:48:14.400 回答
1

关于缓冲区溢出。解决它的最佳方法是响应另一个线程上的事件来完成工作。我这样做

// 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
     }
}

这样我就不会错过任何活动

于 2011-02-11T11:19:29.110 回答
0

好的,这是我对问题的解决方案:

仅用于删除命令:

我实现了 2 个列表,一个用于文件删除,一个用于文件夹删除。

文件列表条目没有超时。如果我删除一个文件,我会创建一个列表条目,如果我收到预期的删除事件,我会像以前一样删除该条目。

文件夹列表条目在创建后没有超时。我可以通过特殊方法手动命令它们在一秒钟后超时。如果我删除一个文件夹,我会添加一个 deleteFolder 列表条目。由于此删除文件夹条目,此文件夹或文件或子文件夹或子文件夹文件中的每个删除事件都会被忽略。删除完成后,我为 deleteFolder 条目设置超时。如果删除引发异常,我也会这样做。所以我希望在一秒钟后得到所有事件。因此,无论删除命令是否有效,我都会忽略所有事件。在此之后 deleteFolder 列表条目被删除。

限制: 1. 所有删除事件都必须在删除发生后一秒内发生。2.不允许这样删除文件夹:
删除文件夹(已完成)
再次创建文件夹
等待不到1秒
再次删除文件夹(删除文件夹列表条目超时尚未完成)

希望这对某人有帮助,即使它非常复杂^^

于 2011-02-16T10:28:38.587 回答