FileSystemWatcher:将多个过滤器事件聚合成一个?

Posted

技术标签:

【中文标题】FileSystemWatcher:将多个过滤器事件聚合成一个?【英文标题】:FileSystemWatcher: aggregate multiple filter events into a single one? 【发布时间】:2021-10-17 17:35:02 【问题描述】:

以如下代码为例,watcher引发的事件都调用同一个方法:

[NonSerialized]
private FileSystemWatcher Watcher;

private void WatcherInit()

    Watcher ??= new FileSystemWatcher();

    Watcher.Path                  = Application.dataPath;
    Watcher.Filter                = "*.mat";
    Watcher.IncludeSubdirectories = true;
    Watcher.NotifyFilter          = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.CreationTime;

    Watcher.EnableRaisingEvents = true;

    Watcher.Changed += OnWatcherChanged;
    Watcher.Created += OnWatcherCreated;
    Watcher.Deleted += OnWatcherDeleted;
    Watcher.Renamed += OnWatcherRenamed;


private void OnWatcherRenamed(object sender, RenamedEventArgs args)

    DoViewReload();


private void OnWatcherDeleted(object sender, FileSystemEventArgs args)

    DoViewReload();


private void OnWatcherCreated(object sender, FileSystemEventArgs args)

    DoViewReload();


private void OnWatcherChanged(object sender, FileSystemEventArgs args)

    DoViewReload();

这会导致同一个方法被多次调用,而我希望它只调用一次。

在我的例子中,我刷新了 UI,当我创建一个新文件时它发生了 3 次。

我想应该有一些计时器会等待连续的事件并将它们连接起来,然后只发出一个调用;这只是一个猜测,也许我不知道有更好的解决方案。

有什么想法吗?

【问题讨论】:

Watcher.Path = Application.dataPath; 在这行代码上放一个断点。运行代码。断点命中多少次? 您可能希望将事件合并为延迟,因为 FSW 经常在创建文件的程序仍在使用文件时引发事件 除了@CaiusJard 写的内容之外,您还可以通过从您的代码访问文件(上次访问时间更改)来获取已更改的事件。 这有关系吗? FileSystemWatcher Changed event is raised twice @aybe 我想你忘了回答我的具体问题。此问题的一个非常常见的原因是订阅两次。我只是想确定你是否已经这样做了。 【参考方案1】:

以下模式运行良好:

private void OnWatcherRenamed(object sender, RenamedEventArgs args)

    WatcherTimerRestart();


private void OnWatcherDeleted(object sender, FileSystemEventArgs args)

    WatcherTimerRestart();


private void OnWatcherCreated(object sender, FileSystemEventArgs args)

    WatcherTimerRestart();


private void OnWatcherChanged(object sender, FileSystemEventArgs args)

    WatcherTimerRestart();


private void WatcherTimerRestart()

    WatcherTimer.Enabled = false;
    WatcherTimer.Enabled = true;


private void WatcherTimerCallback(object sender, ElapsedEventArgs e)

    // do the funky stuff you wanted to execute only once

注意事项:

我决定将 UI 切换到特定状态,例如:

等待 I/O 完成...

在这种情况下,将间隔设置为不太低的值,例如 3000 毫秒会更好:

用户有时间阅读消息 实践证明,较低的值是不够的,即使在小文件和/或 SSD 上也是如此 FileSystemWatcher 引发事件的速度很慢

这是一个关于根据用户操作引发的事件的小表格:

User action Callbacks raised
Create Created
Delete Changed, Deleted
Rename Changed, Created, Deleted
Move Changed, Created, Deleted

您可能要注意,具有讽刺意味的是,Renamed 甚至对于重命名操作也根本没有提出;这可能与应用程序如何重命名文件有关,有多种方法可以做到。

【讨论】:

以上是关于FileSystemWatcher:将多个过滤器事件聚合成一个?的主要内容,如果未能解决你的问题,请参考以下文章

C#:FileSystemWatcher - 多个监视文件夹问题

使用filesystemwatcher时怎么处理大文件

使用FileSystemWatcher警告多个文件是否同时更改

创建同一个 FileSystemWatcher 的多个实例

c# FileSystemWatcher如何处理多个文件?

C# FileSystemWatcher - 多个事件