C# 增加堆大小-可能吗

C# 增加堆大小-可能吗,c#,C#,在读取大容量文件时,我使用C#时出现内存不足异常 我需要更改代码,但目前我是否可以增加堆大小(就像在Java中一样)作为一个术语修复 看起来您已经达到了一个.Net进程可用于其对象的内存限制(在32位计算机上,通过使用/3GB启动开关,这是2标准或3GB。请向Leppie&Eric Lippert提供信息) 重新考虑您的算法,或者可能更改为64位计算机会有所帮助。不,这是不可能的。出现此问题的原因可能是您运行的是32位操作系统,并且内存过于分散。尽量不要将整个文件加载到内存中(例如,逐行处理),

在读取大容量文件时,我使用C#时出现内存不足异常


我需要更改代码,但目前我是否可以增加堆大小(就像在Java中一样)作为一个术语修复

看起来您已经达到了一个.Net进程可用于其对象的内存限制(在32位计算机上,通过使用/3GB启动开关,这是2标准或3GB。请向Leppie&Eric Lippert提供信息)


重新考虑您的算法,或者可能更改为64位计算机会有所帮助。

不,这是不可能的。出现此问题的原因可能是您运行的是32位操作系统,并且内存过于分散。尽量不要将整个文件加载到内存中(例如,逐行处理),或者,如果确实需要完全加载,请将其加载到多个较小的部分。

不,您无法在此处看到我的答案:


对于读取大型文件,通常最好是从磁盘中以流的方式读取它们,将它们分块读取,然后一次处理一个文件,而不是预先加载整个文件。

正如其他人已经指出的那样,这是不可能的。NET运行时代表应用程序处理堆分配

根据我的经验,.NET应用程序通常会在内存充足的情况下(或者至少看起来是这样)出现OOM。原因通常是使用了大量集合,如数组、列表(使用数组存储数据)或类似集合

问题是这些类型有时会在内存使用中产生峰值。如果不能满足这些峰值请求,将抛出OOM异常。例如,当列表需要增加其容量时,它会分配一个比当前大小大一倍的新数组,然后将所有引用/值从一个数组复制到另一个数组。类似地,ToArray等操作也会创建数组的新副本。我在大型LINQ操作中也遇到过类似的问题


每个数组都存储为连续内存,因此为了避免OOM,运行时必须能够获得一大块内存。由于DLL加载和堆的一般使用,进程的地址空间可能会被分割,因此在抛出OOM异常的情况下,这并不总是可能的

您处理的是哪种文件

您最好使用StreamReader并返回ReadLine结果(如果是文本的话)

当然,您将保留一个文件指针,但最坏的情况会大大减少


对于二进制文件也有类似的方法,例如,如果要将文件上载到SQL,则可以读取字节[],并使用SQL指针机制将缓冲区写入blob的末尾。

是否一次读取所有文件?是否可以一次读取和处理一点数据。我相信.net现在也有内存映射,除非您使用/3GB启动开关,否则32位上的进程限制是2GB。我模糊地记得32位系统上的.NET应用程序限制为800MB或其他。@OregonGhost:很可能如果您分配一个800MB的连续块(如数组),您将没有足够的虚拟空间。让我们在这里准确地说。一个进程可以有任意多的内存——32位窗口上的每个进程的内存限制是足够大的,实际上你永远无法达到。在所有这些内存中,一次只能将其中的2GB映射到用户地址空间。或者,如果您有3GB交换机,则可以映射3GB。(3GB开关不提供4GB的地址空间;之所以称为“3GB开关”是有原因的。)由于.NET堆始终映射到用户地址空间,这限制了托管程序自动可用的地址空间。@Eric Lippert,再次编辑。我希望我的简单答案现在是正确的。+1,因为碎片是.NET中OutOfMemoryException的典型原因。GvS是正确的:.NET会自动执行此操作。手动执行此操作是不可能的。这已经改变,在.NET 4.5-64位编译进程中取消了限制,可以使用超过2GB的内存。