我有一段代码,可以将一组记录(超过200k条记录)导出到CSV。在CSV写入期间分配了一个大的内存块,由于某种原因,返回CSV文件后,垃圾回收器不会释放它。
我尝试使用GC.Collect(),但我知道它仅适用于大型堆对象。就在GC.Collect()之后的GC.WaitForPendingFinalizers()也不会释放在此操作期间分配的所有内存。
using (var memoryStream = new MemoryStream())
{
using (var streamWriter = new StreamWriter(memoryStream))
using (var csvWriter = new CsvWriter(streamWriter))
{
csvWriter.Configuration.Delimiter =_configuration["Csv:Delimiter"];
csvWriter.Configuration.CultureInfo = new CultureInfo(_configuration["Csv:Culture"]);
if (!noClassMap)
{
csvWriter.Configuration.RegisterClassMap<U>();
}
//When writing 200,000 records, 500MB get allocated here, and never
freed. Details is an IQueryable that returns a 200,000 records
result.
csvWriter.WriteRecords(details);
}
return new SpreadsheetFile { FileBytes = memoryStream.ToArray(), FileName = fileName + DateTime.Now.ToShortDateString() + ".csv" };
}
我知道可以预期的是,在写入内存流期间,所有对象列表都会在内存中分配。 但是,在Web API返回实际CSV之后,是否不应该释放它?我不确定这是否是预期的,还是某种内存泄漏(运行.NET Core 2.2.3)。
答案 0 :(得分:0)
返回新的SpreadsheetFile { FileBytes = memoryStream.ToArray() ...
memoryStream.ToArray
将所有数据存储到内存中的array
中,并通过FileBytes
的{{1}}属性对其进行引用,这就是为什么GC无法释放数据的原因。
如果您认为SpreadsheetFile
的实例不应该保留,请使用内存分析器查看将其保留在内存中的原因。