跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

C#怎么实现文件监控_C#如何使用FileSystemWatcher监听文件变化【实用】

FileSystemWatcher 默认配置下常因路径非法、权限不足、NotifyFilter与Filter不匹配、缓冲区溢出或未设IncludeSubdirectories而失效;须用本地绝对路径、合理设置过滤器、启用子目录监听、增大缓冲区并强引用防止GC回收。 FileSystemWatcher 能用,但默认配置下大概率不工作——不是代码写错了,而是路径、权限、生命周期或缓冲区这四点卡住了。 Path 必须是本地绝对路径,UNC 和映射盘符直接失效 常见现象:
EnableRaisingEvents = true
也设了,事件回调一个没触发。根本原因常是路径非法。
Path
不能是相对路径(如
"./logs"
)、UNC 路径(如
r"\servershare"
)或网络映射盘符(如
"Z:\data"
),否则静默失败,无异常 必须用本地物理路径,例如
r"C:MyAppData"
;可用
Path.GetFullPath()
转换相对路径确保合规 若程序以管理员身份运行,而目标目录属普通用户(如
C:UsersAliceDocuments
),UAC 隔离可能导致监听被拦截 避免监控系统路径(如
C:Windows
),部分 Windows 版本会直接屏蔽通知 NotifyFilter 和 Filter 不协同,事件就“看不见”
Filter
控文件名匹配,
NotifyFilter
控变更类型——两者缺一不可,且默认值极窄。 设了
Filter = "*.log"
却没调
NotifyFilter
,连重命名都收不到:因为默认只含
FileName | DirectoryName
,不含
LastWrite
关心内容修改?用
NotifyFilters.LastWrite
或
NotifyFilters.Size
要捕获新建/删除/重命名?组合写:
NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.CreationTime
跳过编辑器临时文件?在事件处理器里加判断:
if (e.Name.StartsWith("~$") || e.Name.EndsWith(".tmp")) return;
Changed 事件触发太早?防抖和线程安全必须做 大文件写入时
Changed
常在写完前触发,直接读会抛
IOException
(“正由另一进程使用”)。 C知道 CSDN推出的一款AI技术问答工具 下载 别在事件回调里立刻打开文件——先加
await Task.Delay(100)
,再检查
File.GetLastWriteTimeUtc(path)
是否稳定 更可靠方式:尝试以独占模式打开
File.Open(path, FileMode.Open, FileAccess.Read, FileShare.None)
,捕获
IOException
就说明还在写 事件回调运行在线程池线程上,更新 WinForm/WPF 控件前必须用
Control.Invoke
或
Dispatcher.BeginInvoke
禁止在回调里做耗时操作(解析 JSON、上传 HTTP),否则事件队列堆积,后续通知直接丢失 服务或后台程序中失效?GC 回收和目录校验是主因 Windows Service 或长时间运行的后台任务里,
FileSystemWatcher
经常“突然不响”,基本不是它坏了,而是被回收或启动条件不满足。 必须用
private readonly FileSystemWatcher _watcher
强引用,否则 GC 可能在任意时刻回收对象 启动前务必校验目录存在:
if (!Directory.Exists(path)) throw new InvalidOperationException($"监控路径不存在: {path}");
EnableRaisingEvents = true
必须在所有属性(
Path
、
Filter
、
IncludeSubdirectories
等)设置完毕后最后调用,否则初始事件可能漏掉 缓冲区溢出是隐形杀手:解压、Git checkout 等批量操作易填满默认 8KB 缓冲区,导致静默丢事件;可设
InternalBufferSize = 64 * 1024
,但治标不治本 最易被忽略的是:递归监听子目录必须显式设
IncludeSubdirectories = true
,默认只看一级——这个开关不打开,
C:logssubpp.log
的修改永远进不了你的
Changed
回调。

相关文章