我正在编写一个监视网络目录并在 Windows Server 2008 机器上运行的工具,FileSystemWatcher 的 OnChanged 事件正在由任何未使用 Windows 7 的计算机放置在网络驱动器上的文件正确触发,由于某种原因,如果在 Windows 7 计算机上(一次)复制的文件数量超过 19 个,则不会触发任何事件,尽管如果文件是单独完成的,则它可以工作.是否有解决方法,或者这正是 Windows 7 内核对 FSW 事件的行为方式?
I am writing a tool that monitors a network directory and is running off of a Windows Server 2008 machine, the OnChanged event for the FileSystemWatcher is being fired correctly from files placed on the network drive by any computer that is not using Windows 7, for some reason if the amount of files copied is more than 19 on a windows 7 computer (at once) then no events are fired although it works if files are done individually. Is there a workaround for this or is that just how the Windows 7 kernel behaves with FSW events?
只是为了澄清它在从 XP 机器复制时适用于数千个文件.(该软件仍在 2008 服务器机器上).
Just to clarify it works for thousands of files when copied from an XP machine. (The software is still on the 2008 server machine).
来自 MSDN:
Windows 操作系统会通知您的组件在由 FileSystemWatcher 创建的缓冲区中的文件更改.如果短时间内有很多变化,缓冲区可能会溢出.这会导致组件丢失对目录更改的跟踪,并且它只会提供一揽子通知.使用 InternalBufferSize 属性很昂贵,因为它来自无法换出到磁盘的非分页内存,因此请保持缓冲区小而大,以免错过任何文件更改事件.为避免缓冲区溢出,请使用 NotifyFilter 和 IncludeSubdirectories 属性,以便您可以过滤出不需要的更改通知.
The Windows operating system notifies your component of file changes in a buffer created by the FileSystemWatcher. If there are many changes in a short time, the buffer can overflow. This causes the component to lose track of changes in the directory, and it will only provide blanket notification. Increasing the size of the buffer with the InternalBufferSize property is expensive, as it comes from non-paged memory that cannot be swapped out to disk, so keep the buffer as small yet large enough to not miss any file change events. To avoid a buffer overflow, use the NotifyFilter and IncludeSubdirectories properties so you can filter out unwanted change notifications.
如果增加缓冲区大小还不够,并且您无法控制一次触发事件的文件数量,则必须添加额外的轮询.
If increasing the buffer size is not sufficient and you cannot control how many files are triggering events at a time you would have to add additional polling.
另请参阅此相关问题:
FileSystemWatcher 不当多个文件同时添加到目录时正常工作......
更新:
简单地增加缓冲区大小可能很诱人,但应该小心操作.事实上,在网络访问方面存在 64k 的限制.FileSystemWatcher
类正在使用 Windows API 函数 ReadDirectoryChangesW
下面有这个限制:
It might be tempting to simply increase the buffer size but this should be done with care. In fact, there is a 64k limitation when it comes to network access. The FileSystemWatcher
class is using the Windows API function ReadDirectoryChangesW
underneath which has this limit:
当缓冲区长度大于 64 KB 并且应用程序正在通过网络监视目录时,ReadDirectoryChangesW 失败并显示 ERROR_INVALID_PARAMETER.这是由于底层文件共享协议的数据包大小限制.
ReadDirectoryChangesW fails with ERROR_INVALID_PARAMETER when the buffer length is greater than 64 KB and the application is monitoring a directory over the network. This is due to a packet size limitation with the underlying file sharing protocols.
如果您想更深入地了解修改缓冲区大小的成本,您应该在这里查看 Microsoft 的 Walter Wang 的帖子:
If you want to get a deeper understanding on the cost of modifying the buffer size you should have a look at the post of Walter Wang of Microsoft here:
FileSystemWatcher 跨网络(全文引用如下)
FileSystemWatcher across the network (full post quoted below)
很抱歉,FileSystemWatcher.InternalBufferSize没有说得很清楚监控网络时的缓冲区大小小路.建议不要超过64K监控网络路径时.
I'm sorry that the documentation of FileSystemWatcher.InternalBufferSize didn't state very clear about the buffer size when monitoring network path. It's recommended not exceeds 64K when monitoring network path.
FileSystemWatcher 基本上是一个 .NetWin32 的包装器ReadDirectoryChangesW API.使用ReadDirectoryChangesW,您创建并指定操作系统将使用的缓冲区填充更改.然而,中没有提到的阅读DirectoryChangesW 文档(但在FileSystemWatcher 文档)是文件系统创建一个内部内核用于存储更改信息的缓冲区暂时直到它有机会更新用户缓冲区.的大小创建的内核缓冲区是中指定的相同尺寸ReadDirectoryChangesW 并被创建在非分页池内存中.每次一个 FileSystemWatcher/创建 ReadDirectoryChangesW/调用,一个新的内核缓冲区也是已创建.
FileSystemWatcher is basically a .Net wrapper for the Win32 ReadDirectoryChangesW API. To use ReadDirectoryChangesW, you create and specify a buffer that the OS will populate with the changes. However, what is not mentioned in the ReadDirectoryChangesW documentation (but is hinted in the FileSystemWatcher docs) is that the file system creates an internal kernel buffer to store the change information temporarily until it has the chance to update the user buffer. The size of the kernel buffer that is created is the same size that is specified in ReadDirectoryChangesW and is created in non-paged pooled memory. Every time a FileSystemWatcher / ReadDirectoryChangesW is created / called, a new kernel buffer is also created.
内核内存池(分页和非分页)在系统中预留设备驱动程序的地址空间和其他要使用的内核组件.他们动态增长和收缩必要的.的当前大小去游泳池可以很容易地看到任务的性能选项卡经理.池子会变大动态直到达到最大值在启动时计算的值并且取决于可用的系统资源(主要是 RAM).你不想要达到这个最大值,否则各种系统服务和驱动程序将开始失败.然而,这计算出的最大值并不容易可用的.确定最大值池大小,您需要使用内核调试器.如果你有兴趣有关系统的更多信息内存池,我建议你查看 MSPress 书中的第 7 章所罗门的 Windows 2000 内部和鲁西诺维奇.
The kernel memory pools (paged and non-paged) are set aside in the system address space for device drivers and other kernel components to use. They grow and shrink dynamically as necessary. The current size of the pools can be easily seen by going to the Performance tab of the Task Manager. The pools will grow dynamically until they hit a maximum value which is calculated at boot time and depends on available system resources (mostly RAM). You do not want to hit this maximum value or else various system services and drivers will start failing. However, this calculated maximum value is not easily available. To determine the maximum pool sizes, you need to use a kernel debugger. If you are interested in further information about the system memory pools, I recommend that you look at Chapter 7 in the MSPress book Inside Windows 2000 by Solomon and Russinovich.
考虑到这一点,没有关于缓冲区大小的建议您可以使用.当前和最大值系统池的大小将因客户而异.但是,您可能不应该去每个 FileSystemWatcher 超过 64k/ReadDirectoryChangesW 缓冲区.这源于有一个事实网络访问的 64k 限制为记录在 ReadDirectoryChangesW 中.但最终你将拥有测试各种应用程序预期的目标系统,以便您可以调整你的缓冲区.
With this in mind, there is no recommendation on what size buffers you can use. The current and maximum size of the system pools are going to be varied from client to client. However, you probably should not go over 64k for each FileSystemWatcher / ReadDirectoryChangesW buffer. This stems from the fact that there is a 64k limitation with network access as documented in ReadDirectoryChangesW. But in the end you are going to have to test the application on a variety of expected target systems so that you can tune your buffer.
存在与 .Net 相关的开销应用程序,我想一个Win32 ReadDirectoryChangesW 程序或许能够取得更好的成绩相同缓冲区大小的性能.然而,以非常快和众多文件更改,缓冲区溢出将是不可避免的,开发商正在走必须处理案件时发生溢出,例如手动枚举要检测的目录变化.
There is overhead associated with .Net applications and I imagine that a Win32 ReadDirectoryChangesW program might be able to achieve better performance with the same buffer size. However, with very fast and numerous file changes, buffer overruns will be inevitable and the developer is going to have to handle the case when an overrun occurs such as manually enumerating the directory to detect the changes.
总之,FileSystemWatcher 和ReadDirectoryChangesW 是一个轻量级文件更改检测将有它的机制限制.更改日记帐现为另一种机制,我们会考虑一个中等重量的解决方案,但是仍然有限制:
In conclusion, FileSystemWatcher and ReadDirectoryChangesW are a lightweight file change detection mechanism that is going to have its limitations. Change Journals is another mechanism which we would consider a medium-weight solution, but would still have limitations:
http://msdn.microsoft.com/en-us/library/aa363798%28VS.85%29.aspx
重量级的解决方案是编写一个专用的文件系统过滤器位于文件系统中的驱动程序堆栈和监控文件系统变化.当然这将是最复杂的方法.大多数病毒扫描仪、备份软件和文件系统监控实用程序,例如filemon (www.sysinternals.com)实现一个过滤器驱动程序.
Heavy-weight solutions would be to write a dedicated file system filter driver that sits in the file system stack and monitors file system changes. Of course this would be the most complex approach. Most virus scanners, backup software, and file system monitoring utilities such as filemon (www.sysinternals.com) implement a filter driver.
我希望以上解释能帮助你了解问题的根本原因你正在经历.请回复让我们知道您是否需要更多信息.谢谢.
I hope above explanation helps you to understand the root cause of the issue you're experiencing. Please reply to let us know whether or not you need further information. Thank you.
这篇关于FileSystemWatcher 和 Windows 7的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!