3

我遇到了以下代码中发生的严重内存泄漏:

 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 报告这是因为 IDataReader 指向的行没有被 GC 收集。但是,当我注释掉以下行时,没有泄漏,这就是我将问题隔离到这段代码的方式。

bulkCopy.WriteToServer(reader);

有没有人建议如何防止内存泄漏?

先感谢您。

调用代码:

 var reader = datatable.CreateDataReader();
 BulkInsert(tablename, reader, connectionString);
 reader.Dispose();
 datatable.Dispose();
4

2 回答 2

4

我绝对讨厌回答我自己的问题,但我终于找到了解决方案,虽然我为犯这个错误而感到愚蠢,但我只是想把它作为答案发布,以防其他人遇到这个问题,所以没有其他人在这上面浪费宝贵的时间。

内存泄漏根本不是提供的代码段 - 事实上它根本不是泄漏......

查看性能分析,我发现 BulkCopy 调用是我整个程序的瓶颈。我有一个生产者-消费者模式为其提供数据表以供其插入。

我以为 Memory Profiler 向我展示了在我运行代码时没有被处理的 DataTable 对象。这些实际上是等待插入的排队表,但是因为我正在重新使用测试数据,所以排队表已经在数据库中(因此似乎已经插入)。

通过注释掉 BulkCopy 行,我实际上消除了瓶颈,数据表被快速处理,因此内存分析器上没有显示任何问题。这使得 Bulkcopy 行看起来有问题。

当我用 1 秒的延迟替换 BulkCopy 代码时,这还不足以成为瓶颈。只有当我用 5 秒的延迟替换 BulkCopy 时,我才注意到我的 Consumer Producer Queue Size 失控......因此我的内存很快就耗尽了。

感谢所有花时间在这个问题上的人。很抱歉,它没有更有趣的答案。

于 2013-01-15T17:46:21.200 回答
2

您可能需要处置阅读器,以便 GC 收集它。在您的 finally 块中尝试调用 Dispose。

finally
{
    //reader.Close();
    reader.Dispose();
}
于 2013-01-15T16:22:52.580 回答