【问题标题】:Why does Perl's Win32::ChangeNotify fire two events when a file changes?为什么 Perl 的 Win32::ChangeNotify 在文件更改时会触发两个事件?
【发布时间】:2014-07-09 17:25:00
【问题描述】:

我想在更改源或测试时自动运行prove,我正在使用Win32::ChangeNotify,但我不知道为什么即使是单个文件更改,while 正文也会运行两次,我实际上想要监视所有更改,但只执行一次操作。

require Win32::ChangeNotify;

$notify = Win32::ChangeNotify->new("./", 1, "LAST_WRITE");

while (my @events = $notify->wait) {
    print @events, "----\n";
    $notify->reset;
}

【问题讨论】:

    标签: windows perl winapi


    【解决方案1】:

    Raymond Chen 在Why does saving a file in Notepad fire multiple FindFirstChangeNotification events? 中讨论了类似的话题

    记住Read­Directory­ChangesW function 的最初设计目标:它是为了让应用程序缓存目录列表并逐步更新它。鉴于这些设计目标,除了减少抖动的性能优势之外,不需要在内核中过滤掉多余的通知。理论上,ReadDirectoryChangesW 可以每 5 秒报告一次虚假更改,并且该函数的目标受众仍然可以正常运行(尽管不是最理想的)。

    鉴于这种预期的使用模式,Read­Directory­ChangesW 的任何消费者都需要接受您收到的任何通知都包含您所需的最少信息,以使您的缓存目录信息保持最新,但它也可能包含额外信息。 如果您只想响应实际更改,则需要将新文件属性与旧文件属性进行比较。强调我的

    而且,他在下面进一步澄清:

    文件系统更改通知不检查写入是否等于先前的数据。 (这对于大文件写入来说非常昂贵。)记住更改通知的目的。 虚假通知是合法的。 -Raymond(再次强调一下)

    【讨论】:

    • $notify->wait 不返回任何关于哪个文件被修改的信息,对我来说比较文件属性并不容易,我也不在乎,我只想在某些情况下调用外部命令文件已更新。也许我可以忽略一个周期内的连续事件,但我不知道是否有更好的解决方案。
    • @Sawyer 更好的解决方案是实际查看文件的最后修改日期,并查看其中是否有任何实际更新。如果不是,那么您可以将通知视为虚假通知而忽略。
    • @Sawyer 我知道什么对您最方便,但关键是底层操作系统 API 中没有任何内容可以保证您认为是单个更改会触发单个通知. Read­Directory­ChangesW 给出了更改。
    【解决方案2】:

    File::ChangeNotify 提供更好的事件并且它是跨平台的。

    use File::ChangeNotify;
    use Data::Dumper;
    
    $| = 1;
    
    my $watcher = File::ChangeNotify->instantiate_watcher(
        directories => [ 't', 'lib' ],
        filter => qr/\.t|\.pl|\.pm/,
    );
    
    while (my @events = $watcher->wait_for_events) {
        print Dumper(@events);
    }
    

    当单个文件被修改时,它会打印单个事件,至少这是我观察到的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-02
      • 2023-04-05
      • 1970-01-01
      • 2014-10-05
      • 1970-01-01
      • 1970-01-01
      • 2019-04-22
      • 2015-01-10
      相关资源
      最近更新 更多