FileSystemWatcher - 第二次不触发事件

时间:2010-12-27 20:18:32

标签: c# 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;
        }
    }

任何人都知道为什么我需要让睡眠(或断点)让代码再次运行?

4 个答案:

答案 0 :(得分:1)

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

  

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

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

答案 1 :(得分:1)

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;
}

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

我在这里遇到了完全相同的问题(运行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中的一个错误。