FileSystemWatcher更改事件(对于“LastWrite”)是不可靠的

时间:2012-03-05 07:26:36

标签: c# .net filesystemwatcher

我正在尝试在磁盘上更新文件时收到通知。我有兴趣在刷新发生后立即收到此通知,但似乎FileSystemWatcher只会在流打开或关闭时发送事件。

在下面的代码中,我正在写一个文件并反复刷新缓冲区到磁盘。然而,FileSystemWatcher只在写入开始时和在结束时通知我一次。

还有其他方式来获取这些通知吗?或者我应该使用民意调查吗?

代码:

class Program
{
    static void Main(string[] args)
    {
        FileSystemWatcher watcher = new FileSystemWatcher(Environment.CurrentDirectory, "Test.txt");
        watcher.Changed += watcher_Changed;
        watcher.EnableRaisingEvents = true;

        using(TextWriter writer = new StreamWriter("Test.txt"))
        {
            WriteData(writer);
            WriteData(writer);
            WriteData(writer);
            WriteData(writer);
        }

        Thread.Sleep(10000);
    }

    private static void WriteData(TextWriter writer)
    {
        writer.WriteLine("Hello!");
        writer.Flush();
        Console.WriteLine(DateTime.Now.ToString("T") + "] Wrote data");
        Thread.Sleep(3000);
    }

    static void watcher_Changed(object sender, FileSystemEventArgs e)
    {
        Console.WriteLine(DateTime.Now.ToString("T") + "] Watcher changed!");
    }
}

更新1

我已经更正了DateTime的ToString函数来显示秒数。以下是上面代码的输出:

11:37:47 AM] Watcher changed!
11:37:47 AM] Wrote data
11:37:50 AM] Wrote data
11:37:53 AM] Wrote data
11:37:56 AM] Wrote data
11:37:59 AM] Watcher changed!

谢谢!

2 个答案:

答案 0 :(得分:3)

我认为你的一个问题是你的所有写入都会在事件获得cpu-time片段之前执行。 MSDN states

  

当对正在监视的目录中的文件或目录的大小,系统属性,上次写入时间,上次访问时间或安全权限进行更改时,将引发Changed事件。

我做了一个测试并在每次调用WriteData(...)后插入Sleeps,我得到的是

  

09:32] Watcher改变了!

     

09:32] Watcher改变了!

     

09:32] ----->写了数据

     

09:32] ----->写了数据

     

09:32] ----->写了数据

     

09:32] ----->写了数据

     

09:32] Watcher改变了!

     

09:32] Watcher改变了!

我想这种证明在调用Flush()之后偶数被触发,这只是一个关于事件处理程序何时执行的问题(我假设它也将事件分组)。 我不知道您项目的具体需求,但我不会进行民意调查。看起来像浪费,因为FileSystemWatcher在我看来做了你想做的事。

编辑:好的,我猜我的大脑还没有准备就绪,当我发布这篇文章的时候。 您打开和关闭流时触发的结论似乎更符合逻辑和正确。 我想我正在寻找“证明”,当你打电话给它时会发射,因此发现它 - 不知何故。

<强>更新 我只是在USN-Journal捅了一下,似乎不会得到你想要的东西,因为它只在文件关闭时写入记录。 - &GT; http://msdn.microsoft.com/en-us/library/aa363803(VS.85).aspx 我还发现USN-Viewer in C#http://social.msdn.microsoft.com/Forums/en/csharpgeneral/thread/c1550294-d121-4511-ac32-31551497f64e可能也很有趣。

我还运行DiskMon以查看它是否实时获得了更改。它没有,但我不知道这是否有意。但是,两者的问题是它们需要管理员权限才能运行。 所以我猜你会被FileSystemWatcher困住。 (无论如何,你需要更新的是什么,它不像你可以在另一个程序打开/锁定时读取文件。)

ps:我刚刚注意到你是BugAid的开发者,我最近才意识到这一点 - 它看起来很棒:)

答案 1 :(得分:3)

它与FileSystemWatcher无关。观察者对文件系统的LastWrite属性的更新作出反应。

E.g。 NTFS不会在每次写入时更新LastWrite。该值被缓存,仅在流关闭时或在其他未指定的时间写入。 This document

  

时间戳因各种原因而在不同时间更新。关于文件时间戳的唯一保证是,当关闭进行更改的句柄时,文件时间会正确反映。 [...] NTFS文件系统在最后一次访问后最多1小时延迟更新文件的上次访问时间

我假设类似的缓存适用于写