【问题标题】:FileSystemWatcher for notification用于通知的 FileSystemWatcher
【发布时间】:2013-09-16 14:11:25
【问题描述】:

我正在创建一个使用 FileSystemWatcher 的 Windows 应用程序。 FileSystemWatcher 监视某些目录的更改。并且每次将某个文件添加到此目录时,FileSystemWatcher 都必须将有关此文件的信息添加到 XML 文件中。一切正常,但是,例如,当我同时添加 100 个文件时(假设某些应用程序将这些文件添加到目录中),并不是每个文件的信息都出现在这个 xml 文件中。

我想使用队列。并使用它将项目添加到此集合中。并使用计时器。计时器将从该集合中向 XML 添加信息。这是个好主意吗?

谁能告诉我该怎么做?


所以我认为我必须创建一个 Windows 应用程序和一个 Windows 服务。 WinApp 只会将信息添加到 EventLog,Windows Service 会读取 EventLog 信息并将其写入 XML。我认为这将是最好的方法。我正在等待好的建议

【问题讨论】:

  • FileSystemWatcher 对这类东西很挑剔。
  • 感谢阿萨夫拉维。我知道我的英语不够好。

标签: c# notifications filesystemwatcher


【解决方案1】:

正如 Michael Stum 在他的回答中所写,您可以尝试增加缓冲区大小 (FileSystemWatcher.InternalBufferSize)。但是请注意,您不应将此值设置为过高的值。此外,恕我直言,这可能只是一个临时修复,看看当您同时向文件夹添加更多文件时会发生什么。

如果增加缓冲区大小没有帮助,我已经阅读了您可以尝试的其他一些事情:

  • 如果你订阅了FileSystemWatcher的通知事件,尽量让你的事件处理函数尽量简短; IE。确保执行不会在那里停留太久。如果您必须为每个文件通知做大量工作,您可以尝试启动一个单独的线程并在那里进行处理;然后,您的事件处理程序可以非常快速地返回给调用者(并且文件通知会更快地从缓冲区/队列中删除)。

  • 不要使用FileSystemWatcher 提供的任何其他信息,除了基本通知发生了变化。一旦您收到任何文件更改通知,请等待一小段时间,直到没有更多通知到达(即等待 100 个同时文件更改通知中的最后一个通知)。然后手动列出目录的内容并将所需的信息传输到您的 XML。

    这有一个主要缺点:手动检测是否以及哪些文件已被删除、重命名或创建并不容易。您的程序必须保留最后一个目录列表,与当前列表进行比较以找出更改的内容。

    这样做的好处是您可以相当确定不会因为某些FileSystemWatcher 缓冲区溢出而丢弃任何更改。

【讨论】:

    【解决方案2】:

    FileSystemWatcher 有一个用于更改的内部缓冲区。当有很多快速变化时,缓冲区可能无法捕获所有事件。

    尝试将InternalBufferSize 增加到更高的值。

    您可以将缓冲区设置为 4 KB 或更大,但不得超过 64 KB。为获得最佳性能,请在基于 Intel 的计算机上使用 4 KB 的倍数。

    系统将文件更改通知组件,并将这些更改存储在组件创建并传递给 API 的缓冲区中。每个事件最多可以使用 16 个字节的内存,不包括文件名。如果短时间内有很多变化,缓冲区可能会溢出。这会导致组件丢失对目录更改的跟踪,并且它只会提供一揽子通知。增加缓冲区的大小会产生以下影响:

    增加缓冲区大小可以防止丢失文件系统更改事件。请注意,由于依赖于 Windows 操作系统,当错过事件或超出缓冲区大小时,FileSystemWatcher 类的实例可能会引发错误事件。

    增加缓冲区大小是昂贵的,因为它来自无法换出到磁盘的非分页内存,因此请保持缓冲区尽可能小。为避免缓冲区溢出,请使用 NotifyFilter 和 IncludeSubdirectories 属性过滤掉不需要的更改通知。

    为了诊断,也许你应该先订阅Error Event,看看它是否真的是缓冲区溢出。

    如上所述,将NotifyFilter 设置为所需的最小标志,如果您只想跟踪更改,则可以是NotifyFilters.LastWrite

    【讨论】:

      【解决方案3】:

      MSDN 文档中有一条重要说明可以帮助您更可靠地检测更改:

      保持事件处理代码简短 尽可能。

      我怀疑(但不确定)这是因为文件系统事件是在主观察者线程中引发的,所以任何时候你花在处理事件上都会创建一个窗口,在该窗口中可能无法检测到更改。按照您描述解决方案的方式,您似乎正在回调中执行 I/O(写入 XML 更改日志文件),根据 API 中的标准,这肯定是内联的工作量太大文档。如果您对某个事件有很多工作要做,请将您的事件交给一个单独的线程进行处理,以便您可以尽快返回查看文件系统。

      一个相对简单的方法是使用ThreadPool.QueueUserWorkItem。这意味着您的更改日志仍然不会 100% 与文件系统的状态同步(由于使用单独的线程和队列引入了延迟),但它可能更准确,这似乎是您主要关心的问题。您需要确保线程池调用的WaitCallback 是线程安全的(例如,如果没有lock() 或类似名称,则不会同时写入更改日志),并注意不能保证更改日志条目将按照它们发生的顺序编写(尽管我怀疑FileSystemWatcher 是否保证无论如何)。

      另外,根据 API 指南 - 确保您正在过滤可能的事件集,以便只为您绝对必须看到的事件回调:

      为避免缓冲区溢出,请使用 NotifyFilterIncludeSubdirectories properties 这样你就可以过滤掉 不需要的更改通知。

      【讨论】:

        【解决方案4】:

        如果我理解正确:您正在查看一个目录,当同时添加许多文件时,您只能看到其中一些带有 FileSystemWatcher 的文件。

        您是否尝试过以下操作:在 OnCreated 的事件处理程序中,只需转到文件系统并获取目录的完整内容,而不管事件告诉您什么?

        【讨论】:

        • 是的,这是个好主意。但在xml文件中必须保存数据为:952063\ETIden\filename.xls0 9/23/2010 11:30:03 AM952063\ETIden\952063.rar19/23/2010 11:30:03 AM 删除了 0 和 deleted1 (表示文件 952063\ETIden\filename.xls 已添加但 952063\ETIden \952063.rar已删除)
        • 那么XML文件实际上是一个文件系统更改日志。
        猜你喜欢
        • 1970-01-01
        • 2010-11-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-09
        相关资源
        最近更新 更多