以下面的代码为例,监视器引发的事件都调用相同的方法:
[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次。
我想应该有一些计时器,将等待连续的事件和连接它们,然后只发出一个单一的调用;这只是一个猜测,也许有更好的解决方案,我不知道。
任何想法?
下面的模式最终运行良好:
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切换到一个特定的状态,如:
Waiting for I/O to complete…
在这种情况下,将间隔设置为一个不太低的值,例如3000 ms,效果会更好:
- 用户有时间读取消息
- 一个较低的值在实践中被证明是不够的,即使在小文件和/或SSD
FileSystemWatcher
触发事件缓慢
这里是一个关于根据用户操作引发的事件的迷你表:
用户操作 | 引发的回调 | 创建 | 创建 |
---|---|
删除 | 改变,删除 |
重命名 | 修改、创建、删除 |
改变,创建、删除 |