FileSystemWatcher – 第二次不触发事件

我有一个应用程序启动其他应用程序,然后等待它们创建一个特定的数据文件(它一次监视一个应用程序)。 每次启动应用程序时,它都会监视要创建的特定文件的特定目录。 我正在使用FileSystemWatcher执行此操作(将其设置为目录,然后筛选正确的文件名)。 这是第一次(总是)很好用,但是第二次启动的应用程序永远不会触发事件。 它似乎触发事件的唯一方法是,如果我在事件处理程序中放置一个断点,或者如果我在事件处理程序中有一个Thread.Sleep命令。 这对我来说似乎很奇怪……是否有一些我不知道的种族情况? 这是代码。 注意我有一个Thread.Sleep(500)。 有了这一行,代码每次都有效。 没有它会失败。 我真的不习惯依赖睡眠命令。 我不确定什么条件会导致不能正常工作。

public static void watchFiles(string path) { FileSystemWatcher watcher = new FileSystemWatcher(); watcher.Path = path; watcher.Created += new FileSystemEventHandler(watcher_Handler); watcher.EnableRaisingEvents = true; } public static void watcher_Handler(object sender, FileSystemEventArgs e) { //Hack - the sleep allows the second and third application to be caught by this event Thread.Sleep(500); switch (e.ChangeType.ToString()) { case "Changed": break; case "Deleted": break; case "Created": if (e.Name == "log.dat") { parseDataFile(); moveHTMLtoLMS(); } break; default: break; } } 

任何人都知道为什么我需要让睡眠(或断点)让代码第二次工作?

根据System.IO.FileSystemWatcher类的文档:

Windows操作系统会在FileSystemWatcher创建的缓冲区中通知组件文件更改。 如果在短时间内有许多变化,缓冲区可能会溢出。 这会导致组件无法跟踪目录中的更改,并且只会提供一揽子通知。 使用InternalBufferSize属性增加缓冲区的大小是非常昂贵的,因为它来自无法换出到磁盘的非分页内存,因此请保持缓冲区尽可能小但足够大,以免错过任何文件更改事件。 要避免缓冲区溢出,请使用NotifyFilter和IncludeSubdirectories属性,以便过滤掉不需要的更改通知。

可能是事件没有被足够快地消耗,并且内部缓冲区不够大,无法处理所有通知。 默认情况下,观察程序处理FileNameDirectoryNameLastWrite通知,但您只使用创建事件(文件和目录)。 您的应用程序是否快速连续运行? 我尝试在应用程序的调用(而不是事件处理程序)之间设置延迟,使用更具体的filter(仅使用FileName通知或仅使用Filter属性监视日志文件),增加内部缓冲区大小或任何组合上面提到的。 我认为应该解决你的问题。

 public static void watchFiles(string path) { FileSystemWatcher watcher = new FileSystemWatcher(); watcher.Path = path; watcher.Created += new FileSystemEventHandler(watcher_Handler); watcher.EnableRaisingEvents = true; } 

watcher变量在此方法结束时有资格进行垃圾回收。 不要成为局部变量,而是将其作为类级别成员:

 private static FileSystemWatcher watcher; public static void watchFiles(string path) { if (watcher != null) { watcher.EnableRaisingEvents = false; watcher.Created -= new FileSystemEventHandler(watcher_Handler); } watcher = new FileSystemWatcher(); watcher.Path = path; watcher.Created += new FileSystemEventHandler(watcher_Handler); watcher.EnableRaisingEvents = true; } 

你只能参加一个“创建”活动。 您还需要收听所有其他内容 – OnChanged,OnDeleted – http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx

编辑:当一个程序已存在时,大多数程序都不会“创建”文件。 您可以使用FileMon(现在为Process Monitor – http://technet.microsoft.com/en-us/sysinternals/bb896645 )查看每个程序对您的文件执行的操作。

我在这里遇到了完全相同的问题(运行Windows XP)。 你的黑客解决了这个问题。 我想补充一些可能相关的注释。

在我的例子中,文件名始终是相同的:C:\ blah.txt被创建,删除,创建等等。 另外,我正在使用一个技巧来隐藏我的应用程序:

 Integrator.StartMonitor(); // Start the file monitor! Form f = new Form(); f.ShowInTaskbar = false; f.ShowIcon = false; f.StartPosition = FormStartPosition.Manual; f.Location = new Point(-32000, -32000); f.Show(); f.Hide(); Application.Run(); 

我的文件监视器在调试模式下工作,或者当我添加你的睡眠黑客时。 它当然看起来像FileSystemWatcher一个错误。