这是一个关于实现这一目标的最佳实践的问题。
我有一个FileSystemWatcher
,它应该告诉我用户对文件和文件夹的更改。还观察了细分市场。在同一目录中,我的程序有时也会发生变化。我不希望FileSystemWatcher
检测到这些程序更改的事件。
我的第一个实现是一个列表,我可以在其中添加预期的事件。当我收到文件系统事件时,我检查列表并忽略它,如果它在那里。这听起来不太健壮,但似乎有效。
现在我发现了真正的问题:
D:由FileSystemWatcher
观看。
我有两个这样的文件夹:D:\ folder1 \ folder2
现在我想用我的应用程序删除folder1(其中包含folder2)。所以我把D:\ folder1放在我的删除列表中。然后我打电话给Directory.Delete(@"D:\folder1", true)
。现在我注意到在异常中无法删除folder1(为什么有)。我从列表中删除了删除条目,但是folder2已被删除,我得到了他的FileSystemEvent。所以我得到了D:\ folder1 \ folder2的FileSystem事件。我的程序现在认为用户已经删除了这个文件夹并且做错了。
我现在有了一些想法:
1。)通过删除每个文件和每个文件夹来递归删除文件夹。有了这个,我得到每个子文件夹并提交一个自己的列表条目。我已经实现了它,但它非常非常慢。
2.。)也许有更好的方法在FileSystemWatcher
中设置聪明的过滤器以使我的列表过时?
3.)如果可以删除所有内容,也许只能删除目录树。所以如果它失败了我仍然拥有一切,如果不是,一切都被删除。这对我来说似乎是最优雅的解决方案,但不知道这是否可行?
4.。)是否可以通过我的软件专门锁定所有文件和文件夹?如果这样就可以了,应该可以用一个删除命令删除所有内容,或者以某种方式删除它?
我也愿意接受其他解决方案。
编辑1以使其更清晰:
我只想“看到”文件夹上的用户操作。如果我在这里操作我的程序中的东西,我不想看到这个事件。
通过我的实现,如果文件夹被锁定且无法删除,我将获得子文件夹的事件。
用英语解释并不容易,因为我不是英语母语者;)。
编辑2:
5.。也许可以在FileSystemWatcher
中过滤定义过程中的所有事件?
答案 0 :(得分:2)
我最近做过这样的事情;诀窍是让你的'列表'识别列表中有文件夹名称的位置,如果它期望删除事件,也丢弃该文件夹中任何事件的任何事件,并且只有当它是文件夹本身时才从预测列表中删除它。
我应该警告你,如果有太多事件快速连续发生,你可能会遇到FileSystemWatcher
缓冲区变满的问题;如果是这样,它将触发Error
事件,并且无法通知您一大堆事件。如果您的预测列表在收到事件时删除了项目,则您可能会因为缓冲区溢出而无法收到您想要忽略的事件而忽略未来事件。它也可能变得非常大,因为项目永远不会从列表中删除。
我还没有找到一种可靠的方法来执行此操作,但您可以将FileSystemWatcher
缓冲区的大小设置为最大值以将其缓解到一定程度。
编辑:同样非常重要:返回的事件在不同的线程上执行(除非您的处理程序位于实现ISynchronizeInvoke
的对象上,例如Control
或Form
,并且您将SynchronizingObject
设置为Control
/ Form
。这意味着您需要非常小心地维护您的列表,同时考虑到潜在的竞争条件。我仍在努力使用这个;我的代码在接收到错误事件时刷新预测列表,但是当它处理事件时,自错误以来的其他更改事件已经被触发并处理,并且它会刷新它不应该的事情。
答案 1 :(得分: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
}
}
这样我就不会错过任何活动
答案 2 :(得分:0)
好的,这是我解决问题的方法:
仅用于删除命令:
我实现了2个列表,一个用于删除文件,另一个用于删除文件夹。
文件列表entrys没有超时。如果我删除了一个文件,我会创建一个列表条目,如果我得到了预期的删除事件,我就像以前一样删除该条目。
文件夹列表在创建后没有超时。我可以通过特殊方法手动命令它们在一秒钟之后超时。如果删除文件夹,我会添加一个deleteFolder列表条目。由于此删除文件夹条目,将忽略此文件夹或文件或子文件夹或子文件夹文件中的每个删除事件。删除完成后,我为deleteFolder条目设置超时。如果删除抛出异常,我也会这样做。所以我希望在一秒钟之后得到所有活动。所以如果删除命令有效,我会忽略所有事件。在此之后,删除deleteFolder列表条目。
限制:
1.删除事件发生后,所有删除事件必须在一秒内完成。
2.不允许删除这样的文件夹:
删除文件夹(已完成)
再次创建文件夹
等待不到1秒左右
再次删除文件夹(超时尚未完成删除文件夹列表条目)
希望这有助于某人即使它非常复杂^^