繁体   English   中英

FileSystemWatcher - 第二次不触发事件

[英]FileSystemWatcher - event not firing the second time

我有一个应用程序启动其他应用程序,然后等待它们创建一个特定的数据文件(它一次监视一个应用程序)。 每次启动应用程序时,它都会监视要创建的特定文件的特定目录。 我正在使用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;
        }
    }

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

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

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

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

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

你只能参加一个“创建”活动。 您还需要收听所有其他内容 - 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一个错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM