我正在尝试隔离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事件,而没有显式地诱导它们。
发布于 2009-11-21 00:25:22
我不完全理解为什么,但是复制一个迭代变量就解决了这个问题。据我所知,LinqToSql以某种方式在每个文档中复制了一份DocumentSubmission。
foreach (Document doc in ImportDocs) {
// make copy of doc that lives inside loop scope
Document copydoc = new Document() {
field1 = doc.field1,
field2 = doc.field2,
// complete copy
};
using (var dc = new DocumentClassesDataContext(connection)) {
byte[] contents = File.ReadAllBytes(copydoc.FileName);
DocumentSubmission submission = new DocumentSubmission() {
Content = contents,
// other fields
};
dc.DocumentSubmissions.InsertOnSubmit(submission); // (A)
dc.SubmitChanges(); // (B)
}
}发布于 2009-11-20 08:01:59
您在哪个操作系统上运行此程序?您的问题可能与Linq2Sql无关,而是与操作系统如何管理大内存分配有关。例如,Windows Server 2008在管理内存中的大型对象方面比XP要好得多。我有过这样的例子,处理大文件的代码在XP上泄漏了,但在Win2008服务器上运行得很好。
HTH
https://stackoverflow.com/questions/1767114
复制相似问题