【发布时间】:2009-11-19 22:44:52
【问题描述】:
我试图在我的 C# 应用程序中隔离“内存泄漏”的来源。此应用程序使用 SQL Server 中的 image 列类型将大量可能较大的文件复制到数据库中的记录中。我正在使用 LinqToSql 和关联对象进行所有数据库访问。
主循环遍历文件列表并插入。在删除了很多样板和错误处理之后,它看起来像这样:
foreach (Document doc in ImportDocs) {
using (var dc = new DocumentClassesDataContext(connection)) {
byte[] contents = File.ReadAllBytes(doc.FileName);
DocumentSubmission submission = new DocumentSubmission() {
Content = contents,
// other fields
};
dc.DocumentSubmissions.InsertOnSubmit(submission); // (A)
dc.SubmitChanges(); // (B)
}
}
在整个输入上运行此程序会产生最终的OutOfMemoryException。 CLR Profiler 显示 99% 的堆由与文件大小相对应的大型 byte[] 对象组成。
如果我同时注释 A 和 B 行,这个泄漏就会消失。如果我只取消注释 A 行,泄漏就会回来。我不明白这是怎么可能的,因为dc 是为循环的每次迭代处理的。
有没有人遇到过这种情况?我怀疑直接调用存储过程或进行插入将避免这种泄漏,但我想在尝试其他方法之前了解这一点。怎么回事?
更新
在 (B) 行之后包含 GC.Collect(); 似乎对任何情况都没有重大改变。这并不让我感到惊讶,因为 CLR Profiler 显示了大量的 GC 事件而没有明确诱导它们。
【问题讨论】:
-
您是否尝试过调用垃圾回收。也许不是每次都调用它,但至少要调用几次。不说是解决办法,只是好奇测试一下。
-
Yuriy:看起来没什么区别。查看我的更新。
-
不记得 CLR 探查器是否会让您跟踪大字节 [] 的根 - 这至少可以告诉您是什么阻碍了它们。我通常使用 DevPartner Studio 的分析器,它有助于追踪这类问题。
-
奇怪-我只是尝试在本地复制它并且它工作正常(我在图像类型的列中做了几千行约 2M 字节 [])而没有增加进程的内存占用( ~14M 在整个运行时稳定)。您是否有可能在您的实体类型上定义了一些导致恶作剧的部分方法?
-
嗯。我没有闲置的 2300 美元,但我会记住这一点。
标签: c# linq-to-sql memory-leaks out-of-memory