在读取大量文件时,使用C#时出现内存不足的异常
我需要更改代码但是暂时可以增加堆大小(就像我在Java中一样)作为一个shaort术语修复?
答案 0 :(得分:7)
.Net自动完成。
看起来你已经达到了.Net进程可以用于其对象的内存限制(在32位机器上,这是2个标准或3GB,使用/ 3GB启动开关。对Leppie& Eric Lippert的信用额度为信息)。
重新考虑您的算法,或者更改64位计算机可能有所帮助。
答案 1 :(得分:5)
不,这是不可能的。出现此问题的原因可能是您在32位操作系统上运行且内存过于分散。尽量不要将整个文件加载到内存中(例如,通过逐行处理),或者当你真的需要完全加载它时,将它加载到多个较小的部分中。
答案 2 :(得分:2)
不,你不能在这里看到我的答案:Is there any way to pre-allocate the heap in the .NET runtime, like -Xmx/-Xms in Java?
对于读取大文件,通常最好从磁盘中流式传输它们,然后一块一块地读取它们,而不是预先加载整个文件。
答案 3 :(得分:2)
正如其他人已经指出的那样,这是不可能的。 .NET运行时代表应用程序处理堆分配。
根据我的经验,当应该有足够的可用内存时(或者至少看起来如此),.NET应用程序通常会受到OOM的影响。这样做的原因通常是使用大型集合,如数组,List(使用数组来存储数据)或类似的。
问题是这些类型有时会在内存使用中产生高峰。如果无法遵守这些峰值请求,则抛出OOM异常。例如。当List需要增加其容量时,它通过分配一个当前大小加倍的新数组然后将所有引用/值从一个数组复制到另一个数组来实现。类似于ToArray等操作会生成数组的新副本。我也看到了大型LINQ操作的类似问题。
每个数组都存储为连续内存,因此为了避免OOM,运行时必须能够获得一大块内存。由于DLL加载和堆的一般使用,进程的地址空间可能会碎片化,因此在这种情况下抛出OOM异常并不总是可行的。
答案 4 :(得分:0)
你在处理什么样的档案?
你可能最好使用StreamReader并返回ReadLine结果,如果是文本的话。
当然,你会保留一个文件指针,但最糟糕的情况会大大减少。
对于二进制文件有类似的方法,例如,如果要将文件上传到SQL,则可以读取byte []并使用Sql Pointer函数将缓冲区写入blob的末尾。