我的程序基本上是这样的:
using(XmlReader reader = XmlReader.Create(File.Open(path, FileMode.Open, FileAccess.Reader, FileShare.Read))
{
//a lot of reader.Read() to read through the file
}
程序以这种方式读取大量小文件(通常为每秒5k),并且在本地计算机上可以正常工作。但是我现在正试图从远程机器提供输入数据。我已经在本地驱动器上的远程主机上创建了一个NTFS符号链接文件夹。因此,当我的机器访问C:\ MyFolder时,它会透明地访问\ NetworkComputer \ MySharedFolder。到目前为止一切都很好!
但是我的程序崩溃了“系统无法打开文件”。 IOException异常。这似乎映射到“ERROR_TOO_MANY_OPEN_FILES”。据我所知,我只在给定时间打开一个文件,因此异常没有意义。
经过一些调试后,我发现了以下内容(使用进程资源管理器)。
当在本地运行时,进程以400个句柄(可能是因为.NET)开始,然后当我按下开始按钮时,句柄数量迅速增加到600,然后减少到400,然后增加到600,等等......这可能是垃圾收集器启动,保持文件句柄数量下降。完成处理文件的过程后,文件句柄的数量很好地返回到400。
从远程计算机读取文件时,我在本地进程监视器中看到完全相同的行为。但是在远程计算机上的进程监视器中,我看到文件句柄的数量增加了大约1800,从不减少,直到程序崩溃。远程计算机上的文件句柄号增加直接与已处理文件的数量相对应。
TLDR: 所以这是我的问题:如何通过符号链接访问远程计算机上的悬空文件句柄?
编辑:
有时会出现另一个异常(IOException)“没有足够的服务器存储可用于处理此命令”。我不知道如何解决这个问题,但我发现了一些额外的信息,仍然不确定这意味着什么http://support.microsoft.com/kb/285089 http://support.microsoft.com/kb/106167
EDIT2:
一个似乎有帮助的解决方案是减慢从远程计算机的读取速度,通过限制到每分钟2000个文件来解决问题,但这不是一个真正有效的解决方案,因为那时工作所需的时间比它必须要长10倍采取。
我还发现一些文章表明增加IRPSstacksize可以解决这个问题,但是由于计算机不是我直接控制的,这可能是不可能的。
答案 0 :(得分:2)
XmlReader
会自动关闭/处置传递的流吗? (即FileStream
返回的File.Open
。)
我不认为这样做,这可以解释为什么你会看到手柄数量攀升然后跌落在本地机器上。在GC触发终结器之前,不会释放句柄,而不是在每个流被处理时。
试试这个,看看这是否有所不同:
using (var fs = File.Open(path, FileMode.Open, FileAccess.Reader, FileShare.Read))
using (var reader = XmlReader.Create(fs))
{
// a lot of reader.Read() to read through the file
}
答案 1 :(得分:1)
听起来像终结器释放内部流而不是你明确地处理它。 试试这个:
using(FileStream steram = File.Open(path, FileMode.Open, FileAccess.Reader, FileShare.Read))
using (XmlReader reader = XmlReader.Create(steram))
{
//a lot of reader.Read() to read through the file
}
答案 2 :(得分:0)
我不确定这种行为是由于访问远程计算机还是由于通过符号链接访问...
也许您可以在没有符号链接的情况下检查访问远程计算机时的行为 - 通过UNC路径和/或驱动器号(smb mount)......
我不能100%肯定,但我认为符号链接是问题的一部分......