处理Exception of type System.OutOfMemoryException was thrown

本文介绍如何通过修改machine.config文件中的memoryLimit属性来调整ASP.NET进程的内存使用上限,以防止因内存不足导致的错误,并提供针对不同服务器内存大小的最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

machine.config文件路径C:/WINDOWS/Microsoft.NET/Framework/v1.1.4322/CONFIG

 

/在ASP.NET Web服务器上,ASP.NET所能够用到的内存,通常不会等同于所有的内存数量。

在machine.config配置文件中,配<processModel>中有一个属性“memoryLimit”,这个属性的值是一个百分值,默认为“60”,即指定了ASP.NET进程(在任务管理器中大家就可以看到ASP.NET的进程,IIS5中为aspnet_wp,IIS6中为w3wp)能够使用所有物理内存的60%。当ASP.NET使用的内存量超过这个限额时,IIS会开始自动回收(recycle)进程,即创建一个新的进程去负责应付Http请求,而将旧进程所占用的内存回收。

当我们有一台很大内存的服务器时,“memoryLimit”这个值是需要进行适当的调整的。比如我们准备了一台chemas-microsoft-comofficemarttags" />t="on">4G内存的服务器,那么t="on">4G×60%=t="on">2.4G。但是,对于Win32操作系统,一个进程所能占用的所有内存空间只有t="on">2G。当ASP.NET进程占用的内存开始达到t="on">2G时,由于它并没有达到t="on">2.4G的“回收阈值”,所以IIS不会启动recycle进程操作,但是由于Win32的限制,实际上已经不能给这个进程分配更多的内存了,于是,OutOfMemoryException就很可能会被抛出了。为了避免这样的情况,我们就必须将“memoryLimit”适当调小,以让IIS更早的进行进程回收。

微软推荐的ASP.NET进程占用内存是不超过60%,并最好使计算出的实际值不超过t="on">800M。就是说,对于一台t="on">4G内存的服务器,最好将“memoryLimit”属性设置成“20”。设置一个适当的回收阈值,让IIS适时的进行进程回收,对于保证整个服务器的稳定运行,避免OutOfMemoryException是非常重要的。

在IIS6中,ASP.NET进程的回收阈值不再由配置节中的“memoryLimit”属性决定,而是由IIS管理器中的应用程序池配置中的设置决定。

但是,即使正确设置了这些配置,也不能保证完全避免OutOfMemoryException的发生,原因可能是多样而复杂的,比如内存回收操作可能耗时太多等等。开发人员要注意的,就是在代码中时刻牢记不要无谓的使用和浪费内存。:)

如果你有一台大内存的服务器,同时对Win32操作系统中对于进程最高使用t="on">2G内存的限制很郁闷,可选的解决方法有两个:
1、使用/3GB模式启动计算机,方法参加文后的链接
2、使用Windows Server 2003 64bits Edition

<think>好的,我现在需要帮助用户解决System.OutOfMemoryException异常的问题,特别是HResult为0x8007000E,发生在程序构造函数中的Offline_DAR_Table1.cs第51行。首先,我要回忆一下这个异常的一般原因和可能的解决方案,同时结合用户提供的引用资料来分析。 根据引用[1],System.OutOfMemoryException通常是由于CLR无法分配足够的内存导致的。虽然这个异常继承自SystemException,但实际原因可能不仅仅是物理内存不足,还可能涉及32位进程的内存限制、内存碎片或大对象堆的问题。用户提到的引用[3]中提到,即使物理内存还有很多,比如剩余十几GB,但程序可能在占用约2.8-3GB时崩溃,这可能是因为32位进程的地址空间限制(通常2GB,最大4GB)。如果用户的程序是32位的,那么即使物理内存足够,进程也无法分配超过这个限制的内存。 接下来,用户的具体错误发生在构造函数中的第51行。需要检查该行代码是否在初始化时分配了大量内存,比如大型数组、集合或数据集。例如,是否有DataTable、DataSet、List或数组被初始化,并且加载了大量数据?根据引用[3]中的情况,DataTable或读取大文件时可能导致这个问题,即使未达到最大行数限制,也可能因为内存碎片或大对象堆无法分配连续内存块。 解决方案方面,首先考虑将程序编译为64位(x64),这样可以利用更多的虚拟内存空间。如果已经是64位,则需要检查是否有内存泄漏或过度分配的情况。使用引用[4]提到的工具如dotMemory或Visual Studio的性能分析器来分析内存使用情况,查找内存异常增长的地方。 另外,可能需要优化数据结构和算法,避免一次性加载所有数据到内存中。例如,使用流式处理逐行读取大文件,或者分块处理数据。对于集合类,考虑使用更节省内存的结构,或者分页加载数据。此外,检查是否有未及时释放的资源,如数据库连接、文件流等,确保及时调用Dispose()或使用using语句。 针对大对象堆的问题,如果频繁分配大对象(超过85KB),可能导致LOH碎片,无法找到连续内存空间。这时可以考虑使用对象池或减少大对象的分配次数,或者使用.NET 4.5及以上版本的LOH压缩功能。 用户提到的HResult=0x8007000E,根据引用[1],这是COR_E_OUTOFMEMORY的标准HRESULT值,进一步确认是内存不足的问题。需要查看Stacktrace中第51行的具体代码,是否存在循环或递归调用导致内存无限增长,或者是否在构造函数中进行了高内存消耗的操作。 总结可能的解决步骤:1. 检查目标平台是否为x64;2. 分析第51行代码的内存使用;3. 使用内存分析工具定位问题;4. 优化内存分配,避免一次性加载过多数据;5. 处理大对象和内存碎片问题。</think>针对System.OutOfMemoryException(HResult=0x8007000E)的解决方案及分析如下: ### 一、异常定位与分析 1. **Stacktrace定位** 错误发生在`E:\5.7test\Offline_DAR_Table1.cs`第51行,需检查构造函数中是否涉及以下操作: - 初始化大型数组或集合(如`List<T>`、`DataTable`) - 一次性加载超大文件或数据集 - 未释放的循环内存分配 2. **HResult=0x8007000E含义** 表示CLR尝试分配内存时失败,常见于32位进程内存超限(2GB用户模式限制)或内存碎片化[^1][^3]。 --- ### 二、具体解决方案 #### 步骤1:检查编译目标平台 - **启用64位进程** 在项目属性 → 生成 → 目标平台选择`x64`,突破32位进程的2GB内存限制(需物理内存充足)[^3]。 #### 步骤2:优化构造函数代码(以第51行为例) - **避免一次性加载数据** 若涉及文件读取或数据库查询,改用流式处理: ```csharp // 错误示例:一次性读取所有行到内存 var allLines = File.ReadAllLines("largefile.txt"); // 正确示例:逐行流式处理 using (var reader = new StreamReader("largefile.txt")) { while (!reader.EndOfStream) { ProcessLine(reader.ReadLine()); } } ``` - **释放非托管资源** 检查是否有未关闭的数据库连接、文件流等,使用`using`语句确保释放。 #### 步骤3:内存管理优化 - **分块处理数据** 若需操作大型集合,按分页加载: ```csharp int pageSize = 1000; for (int i = 0; i < totalRecords; i += pageSize) { var chunk = data.Skip(i).Take(pageSize).ToList(); ProcessChunk(chunk); chunk = null; // 加速GC回收 } ``` - **避免大对象堆(LOH)碎片** 减少分配>85KB的对象(如大数组),或使用`ArrayPool<T>`复用内存[^3]: ```csharp var pool = ArrayPool<byte>.Shared; byte[] buffer = pool.Rent(102400); // 租用100KB缓冲区 // 使用buffer... pool.Return(buffer); // 归还以避免碎片 ``` #### 步骤4:诊断工具辅助 - **使用dotMemory分析内存** 检测内存泄漏和碎片化问题,定位具体对象分配路径[^4]。 - **监控GC行为** 在代码中添加GC统计: ```csharp GC.Collect(); GC.WaitForPendingFinalizers(); Console.WriteLine($"Total Memory: {GC.GetTotalMemory(false)}"); ``` --- ### 三、验证与测试 1. **重现问题** 在开发环境中复现溢出场景,记录内存峰值。 2. **逐步优化** 通过分块加载、流式处理等手段降低单次内存需求。 3. **压力测试** 使用大型数据集验证修改后的稳定性。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值