You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ParallelProcessor中创建DataTable触发OutOfMemoryException求助

问题分析与解决方案

问题背景

在并行处理器(ParallelProcessor)中封装创建DataTable并加载单行数据的逻辑,将其作为表类型参数使用时,部分记录可正常更新,部分触发OutOfMemoryException,报错栈指向System.Data.RBTree1`的内存分配环节,且该问题仅在部分环境出现。

报错信息:

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at System.Data.RBTree1.TreePage..ctor(Int32 size) at System.Data.RBTree1.AllocPage(Int32 size)
at System.Data.RBTree`1.GetNewNode(K key)
at System.Data.DataTable.SetNewRecordWorker(DataRow row, Int32 proposedRecord, DataRowAction action, Boolean isInMerge, Boolean suppressEnsurePropertyChanged, Int32 position, Boolean fireEvent, Exception& deferredException)
at System.Data.DataTable.InsertRow(DataRow row, Int64 proposedID, Int32 pos, Boolean fireEvent)

可能原因

  • 并行任务内存堆积:短时间内大量并行任务创建DataTable实例,每个实例即使仅存单行数据,也包含列定义、内部索引结构等固定开销,累积后超出系统可用内存阈值。
  • 环境配置差异:不同环境的可用内存、GC模式(工作站GC/服务器GC)、线程并发限制不同,部分环境的资源不足以支撑当前并行规模。
  • 资源未及时回收:并行场景下GC回收不及时,已使用的DataTable实例未被快速释放,导致内存占用持续攀升。

解决方案

1. 限制并行并发量

调整ParallelProcessor的最大并发线程数,避免短时间内创建过多DataTable实例,降低内存瞬时压力。

2. 复用DataTable实例

通过对象池复用已初始化的DataTable,避免重复创建带来的内存开销:

// 实现简单的DataTable对象池
using Microsoft.Extensions.ObjectPool;

private static readonly ObjectPool<DataTable> _dataTablePool = 
    new DefaultObjectPool<DataTable>(new DataTablePoolPolicy());

private class DataTablePoolPolicy : IPooledPolicy<DataTable>
{
    public DataTable Create()
    {
        var table = new DataTable();
        table.Columns.Add("ID", typeof(int));
        return table;
    }

    public bool Return(DataTable table)
    {
        table.Rows.Clear();
        return true;
    }
}

// 业务方法中使用对象池
public DataTable GetRecords(List<testData> testData)
{
    var table = _dataTablePool.Get();
    foreach (var item in testData.Select(x => x.ID))
    {
        var dr = table.NewRow();
        dr["ID"] = item;
        table.Rows.Add(dr);
    }
    // 注意:需在DataTable作为参数使用完毕后,调用以下代码归还到池
    // _dataTablePool.Return(table);
    return table;
}

3. 替换为轻量级数据载体

若仅需传递单行数据,直接使用自定义实体类或匿名对象替代DataTable,彻底消除DataTable的额外内存开销;若必须使用表类型参数,可考虑使用流式DataReader(如SqlDataReader)传递数据,减少内存占用。

4. 优化GC配置

在服务器环境启用服务器GC,提升并行场景下的内存回收效率,修改配置文件:

<configuration>
  <runtime>
    <gcServer enabled="true"/>
  </runtime>
</configuration>

5. 控制任务队列积压

确保ParallelProcessor的任务队列不会积压过多未执行任务,避免内存占用持续增长。

内容的提问来源于stack exchange,提问作者Gladstone Jaffrey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 21:15:42