【问题标题】:C# - Predict file system events on folder deleteC# - 预测文件夹删除时的文件系统事件
【发布时间】:2011-06-25 10:09:52
【问题描述】:

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

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

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

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

我现在有了一些想法:

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

2.) 也许有更好的方法可以在 FileSystemWatcher 中设置巧妙的过滤器以使我的列表过时?

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

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

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

编辑 1 使其更清晰:

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

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

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

编辑 2:

5.) 是否可以在FileSystemWatcher 中过滤来自已定义进程的所有事件?

【问题讨论】:

  • 你的问题中关于预测事物的部分在哪里?
  • 我所写的列表是一个预测,因为它包含稍后应该来自 FileSystemWatcher 的预期事件。它的工作原理是:1.) 记住列表 2.) 操作文件/文件夹 3.) 使用列表忽略事件
  • 说真的,我不明白。你期待什么活动?你会得到什么事件?你得到什么例外?请根据这些要点更新您的问题。
  • 关于您上面的想法#3 - 如果您使用的是 NTFS,您可以使用文件系统事务。 msdn.microsoft.com/en-us/magazine/cc163388.aspx - 但是我不知道它们如何在您自己的进程中与文件系统观察者交互。

标签: c# .net filesystemwatcher cascading-deletes


【解决方案1】:

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

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

虽然您可以将FileSystemWatchers 缓冲区的大小设置为最大值以在一定程度上减轻它,但我还没有找到一种可靠的方法来执行此操作。

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

【讨论】:

  • 非常非常有趣...谢谢。你知道这个 FileSystemWatcher 缓冲区有多大吗?我还尝试为列表条目实现预期寿命以稍微清理一下,但问题是 FileSystem 事件(最坏情况)来得有多快?如果你能让我了解最新情况并告诉我你的经历,那就太好了。 1+
  • 如果我有这个终身实现并且它会很健壮,我可以使用正则表达式来删除文件夹并让列表条目超出生命周期。
  • FileSystemWatcher 有一个属性InternalBufferSize。默认值为 8k,但最高可达 64k。 msdn.microsoft.com/en-us/library/…
  • 或者说其他:删除文件夹并获取文件系统事件需要多长时间(最坏情况)...
  • 最坏的情况?很长一段时间,具体取决于该文件夹的位置以及其中的内容。在地球另一端的服务器上使用拨号连接创建一个包含 1000000 个文件和子文件夹的文件夹可能需要几天时间。
【解决方案2】:

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

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

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

【讨论】:

  • 谢谢...我已经有类似的东西了。我只是在考虑电脑非常过载的情况。我不确定它是否可能,但默认的 FileSystemWatcher 可以容纳大约 500 个条目。即使您有一个工作线程并且只是从 FileSystemWatcher 的线程中脉冲事件,这也非常少。所以我不认为将缓冲区设置为最大值是错误的。
【解决方案3】:

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

仅用于删除命令:

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-27
    • 2015-12-06
    • 1970-01-01
    • 2017-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-19
    相关资源
    最近更新 更多