关于本文
本文是通过利用生成式 AI 的自动化生成流程创建的。我们查阅了 Microsoft Learn 的 FileSystemWatcher 规范,并将其整理为一项尝试(TRY),用于将重复事件、防抖和漏检作为独立的问题进行观察。验证状态:📘 已确认 .NET 官方规范・PowerShell 实机未验证
本次的成功条件:即使短时间内对同一个文件触发了多个事件,只要能将后续处理候选合并为 1 次即视为成功。
FileSystemWatcher 并不意味着“保存 1 次就必定触发 1 次 Changed”。微软也解释过,常规的文件系统操作可能会产生多个事件。
冒烟测试(Smoke Test):首先观察原始事件
$dir = Join-Path $env:TEMP 'papanda-watch'
New-Item -ItemType Directory -Force $dir | Out-Null
$w = [IO.FileSystemWatcher]::new($dir)
$w.EnableRaisingEvents = $true
$sub = Register-ObjectEvent $w Changed -Action {
"[EVENT] $([DateTime]::Now.ToString('HH:mm:ss.fff')) $($Event.SourceEventArgs.Name)"
}
"A" | Set-Content (Join-Path $dir 'demo.txt')
"B" | Add-Content (Join-Path $dir 'demo.txt')
Start-Sleep 1
Unregister-Event -SourceIdentifier $sub.Name -ErrorAction SilentlyContinue
$w.Dispose()
查看此处
[EVENT]观察会输出多少行。由于事件数量可能因环境而异,因此不要固定写死“理应输出 2 次”之类的内容。将可能发生重复这一事实本身作为设计条件这一点非常重要。
防抖(debounce)的思路
flowchart LR E1[event] --> T[タイマーを更新] E2[event] --> T E3[event] --> T T -->|静かな時間が経過| J[後続処理を1回]
防抖是将短时间内连续发生的事件“等待其静止后归并为 1 次”的方法。不过,这并非漏检对策。它不是那种能够保证处理 FileSystemWatcher 内部缓冲区溢出或进程停止期间发生变更的持久化队列。
尝试修改一处
对比 100ms 和 1000ms 的等待时间,可以看出合并的难易程度与响应速度之间的权衡(trade-off)。在实际业务中,为了做到“在文件复制完成之前不开始处理”,还需要另外进行就绪判定,例如检查文件大小是否保持不变、是否能够正常打开等。
如果在实际工作中应用
可应用于自动导入共享文件夹的 CSV、扫描版 PDF 的后处理、日志监控等场景。对于日常业务而言,与其“文件一放置就立即处理”,不如构建接收事件 → 防抖 → 确认文件就绪 → 记录已处理 ID的完整流程,这样可以减少故障。
失败与边界
即使使用了防抖,也无法恢复丢失的事件。
我们在其他用例中测试同名文件的覆盖、重命名以及大量投入的情况。
使后续处理具备幂等性,设计成即使接收到两次相同的文件也不会损坏的结构。
在 finally 等块中对 watcher/event 订阅进行善后清理。
