【发布时间】:2015-08-19 06:29:46
【问题描述】:
我有一个数据加载过程,将大量数据加载到DataTable然后做一些数据处理,但是每次作业完成时DataLoader.exe(32位,有1.5G内存限制)并没有释放所有正在使用的内存。
我尝试了3种释放内存的方法:
- DataTable.Clear() 然后调用 DataTable.Dispose() (释放大约 800 MB 内存,但每次数据加载作业完成时仍会增加 200 MB 内存,经过 3 或 4 次数据加载后,由于它引发内存不足异常总内存超过1.5G)
- 设置DataTable为null(不释放内存,如果选择加载更多数据,会抛出内存不足异常)
- 直接调用DataTable.Dispose()(不释放内存,如果选择加载更多数据,会抛出内存不足异常)
以下是我尝试测试的代码(在实际程序中它不是递归调用的,它是由一些目录监视逻辑触发的。这段代码只是为了测试。抱歉造成混淆。):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace DataTable_Memory_test
{
class Program
{
static void Main(string[] args)
{
try
{
LoadData();
Console.ReadKey();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
Console.ReadKey();
}
}
private static void LoadData()
{
DataTable table = new DataTable();
table.Columns.Add("Dosage", typeof(int));
table.Columns.Add("Drug", typeof(string));
table.Columns.Add("Patient", typeof(string));
table.Columns.Add("Date", typeof(DateTime));
// Fill the data table to make it take about 1 G memory.
for (int i = 0; i < 1677700; i++)
{
table.Rows.Add(25, "Indocin", "David", DateTime.Now);
table.Rows.Add(50, "Enebrel", "Sam", DateTime.Now);
table.Rows.Add(10, "Hydralazine", "Christoff", DateTime.Now);
table.Rows.Add(21, "Combivent", "Janet", DateTime.Now);
table.Rows.Add(100, "Dilantin", "Melanie", DateTime.Now);
}
Console.WriteLine("Data table load finish: please check memory.");
Console.WriteLine("Press 0 to clear and dispose datatable, press 1 to set datatable to null, press 2 to dispose datatable directly");
string key = Console.ReadLine();
if (key == "0")
{
table.Clear();
table.Dispose();
Console.WriteLine("Datatable disposed, data table row count is {0}", table.Rows.Count);
GC.Collect();
long lMemoryMB = GC.GetTotalMemory(true/* true = Collect garbage before measuring */) / 1024 / 1024; // memory in megabytes
Console.WriteLine(lMemoryMB);
}
else if (key == "1")
{
table = null;
GC.Collect();
long lMemoryMB = GC.GetTotalMemory(true/* true = Collect garbage before measuring */) / 1024 / 1024; // memory in megabytes
Console.WriteLine(lMemoryMB);
}
else if (key == "2")
{
table.Dispose();
GC.Collect();
long lMemoryMB = GC.GetTotalMemory(true/* true = Collect garbage before measuring */) / 1024 / 1024; // memory in megabytes
Console.WriteLine(lMemoryMB);
}
Console.WriteLine("Job finish, please check memory");
Console.WriteLine("Press 0 to exit, press 1 to load more data and check if throw out of memory exception");
key = Console.ReadLine();
if (key == "0")
{
Environment.Exit(0);
}
else if (key == "1")
{
LoadData();
}
}
}
}
【问题讨论】:
-
我不知道,但我敢打赌您正在释放您的对象,但您遇到了内存碎片问题。编辑:哦,在没有附加调试器的情况下运行你的程序,你会看到不同的行为。附加调试器时,GC 的行为非常不同。
-
@ScottChamberlain 谢谢。但在我的情况下,这个数据加载是在一个目录中观看 exe。为了防止这个 OutOfMemoery 异常,我该怎么办?
-
@ScottChamberlain 好的,我会在发布模式下尝试。
-
在没有调试器的情况下运行更重要,在发布模式下运行会产生较小的变化,但在没有调试器的情况下运行会对行为进行重大更改。
标签: c# memory memory-management datatable