C# FileSystemWatcher更改事件(对于“LastWrite”)不可靠
我正在尝试在磁盘上更新文件时获取通知。我感兴趣的是在刷新发生时立即获得此通知,然而,似乎FileSystemWatcher只会在流打开或关闭时发送事件 在下面的代码中,我正在写入一个文件,并反复将缓冲区刷新到磁盘上。然而,FileSystemWatcher只在写入的开始和结束时通知我一次 是否有其他方法获取这些通知?或者我应该用投票来解决这个问题 守则:C# FileSystemWatcher更改事件(对于“LastWrite”)不可靠,c#,.net,filesystemwatcher,C#,.net,Filesystemwatcher,我正在尝试在磁盘上更新文件时获取通知。我感兴趣的是在刷新发生时立即获得此通知,然而,似乎FileSystemWatcher只会在流打开或关闭时发送事件 在下面的代码中,我正在写入一个文件,并反复将缓冲区刷新到磁盘上。然而,FileSystemWatcher只在写入的开始和结束时通知我一次 是否有其他方法获取这些通知?或者我应该用投票来解决这个问题 守则: class Program { static void Main(string[] args) { FileS
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!
谢谢 我认为您的问题之一是,在事件占用cpu时间之前,所有写入都会被执行。 当对受监视目录中的文件或目录的大小、系统属性、上次写入时间、上次访问时间或安全权限进行更改时,将引发Changed事件 我做了一个测试,在每次调用WriteData(…)后插入Sleeps,得到的结果是 09:32]观察者改变了 09:32]观察者改变了 09:32]------>写入数据 09:32]------>写入数据 09:32]------>写入数据 09:32]------>写入数据 09:32]观察者改变了 09:32]观察者改变了 我想这证明了在调用Flush()之后会立即触发偶数,这只是一个事件处理程序何时执行的问题(我假设它也会对事件进行分组)。 我不知道你们项目的具体需求,但我不会投票。在我看来,这似乎是一种浪费,因为FileSystemWatcher做了您希望它做的事情 编辑:好吧,我想当我发布这篇文章时,我的大脑还没有完全准备好思考。 您的结论是,当您打开和关闭流时,它会触发,这似乎更符合逻辑和正确。 我想我是在寻找“证明”,当你打电话给flush时,它会开火,因此找到了它——不知何故 更新 我刚刚戳了一下USN日志,它似乎也无法满足您的需求,因为它只在文件关闭时写入记录。-> 我还找到了一本书,读起来可能也很有趣 我还运行了DiskMon,看看它是否能实时获得更改。没有,但我不知道这是不是有意的。然而,两者的问题是它们都需要管理员权限才能运行。 所以我猜你一定是被FileSystemWatcher困住了。(无论如何,你需要更新的原因是什么,当文件被其他程序打开/锁定时,你无法读取该文件。)
ps:我刚刚注意到你是BugAid的开发人员,我最近才意识到这一点——它看起来很棒:)它与FileSystemWatcher无关。观察者对文件系统的LastWrite属性的更新做出反应 例如,NTFS不会在每次写入时更新上次写入。该值被缓存,仅在流关闭或在其他未指定的时间写入。说 由于各种原因,时间戳会在不同的时间更新。关于文件时间戳的唯一保证是在关闭进行更改的句柄时正确反映文件时间。[…]NTFS文件系统将文件的更新延迟到最后一次访问后的最后一次访问时间最多1小时
我假设类似的缓存适用于write
FileSystemWatcher
,由于许多原因,它是不可靠的。如果您需要所有更新的可靠通知,请更改双方,并在他们之间使用其他明确的通信渠道。我同意,这将是一个更好的选择,但在我的情况下,这是不可能的。啊,我从您的示例代码/描述中假设您控制了此集成问题双方的代码。如果不是这样的话,我不确定我会推荐什么。我想一想。谢谢你的回答。在我的代码中,在每次写入和刷新之后都会有睡眠(3000),因此FileSystemWatcher在发送事件时不会有任何问题。另外,从您发布的输出来看,FSW在关闭流之前似乎确实没有发送/接收事件。。。我现在已经更正了代码中日期时间的ToString,以更好地显示这一点。很高兴你喜欢BugAid:)如果你有任何问题,请告诉我!哦,我觉得我忽略了这一点很傻,我猜起床后第一件事就是阅读代码不是个好主意。编辑:好的,我现在明白你的意思了。很有趣!是的,这很可能是原因。是的,NTFS写入是缓冲的,只有当缓冲区已满并提交、流已刷新或流已关闭时,才会将其写入磁盘。