我遇到了以下代码中出现的内存泄漏:
public void BulkInsert(string tableName, IDataReader reader, String connectionString)
{
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
using (var bulkCopy = new SqlBulkCopy(connection))
{
bulkCopy.DestinationTableName = tableName;
bulkCopy.BulkCopyTimeout = 900;
try
{
bulkCopy.WriteToServer(reader);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
reader.Close();
}
}
}
}
此代码段执行数千次,因此只需一分钟就会发生内存不足异常。 Ants报告这是因为GC没有收集IDataReader指向的行。但是,当我注释掉以下行时,没有泄漏,这就是我如何将问题与这段代码隔离开来。
bulkCopy.WriteToServer(reader);
有没有人建议如何防止内存泄漏?
提前谢谢。
致电代码:
var reader = datatable.CreateDataReader();
BulkInsert(tablename, reader, connectionString);
reader.Dispose();
datatable.Dispose();
答案 0 :(得分:3)
我绝对不喜欢回答我自己的问题,但我终于找到了解决方案,虽然我觉得这个错误是愚蠢的,但我只是想把它作为答案发布,万一其他人遇到这个问题,所以没有人浪费宝贵的时间对此。
内存泄漏根本没有提供的代码段 - 实际上它根本不是泄漏......
查看性能分析我发现,速度方面BulkCopy调用是我整个程序的瓶颈。我有一个生产者 - 消费者模式,它为DataTables提供插入。
我以为Memory Profiler向我展示了DataTable对象,这些对象在我运行代码时没有被处理掉。这些实际上是等待插入的排队表,但由于我重新使用测试数据,排队的表已经在数据库中(因此似乎已经插入)。
通过注释掉BulkCopy系列,我实际上消除了瓶颈,DataTables正在快速处理,因此Memory Profiler上没有显示任何问题。这使得它看起来像Bulkcopy线路有问题。
当我用1秒延迟替换BulkCopy代码时,这还不足以成为瓶颈。只有当我用5s延迟替换BulkCopy时,我注意到我的消费者生产者队列大小失控......因此我为什么快速耗尽内存。
感谢所有在这个问题上花时间的人。对不起,它没有更有趣的答案。
答案 1 :(得分:2)
您可能需要处理读卡器以便GC收集它。在您的finally块尝试调用Dispose。
finally
{
//reader.Close();
reader.Dispose();
}