Dispose()不会阻止内存不足异常

本文关键字:内存不足 异常 Dispose | 更新日期: 2023-09-27 18:29:44

我有一个巨大的日志文件,其中大约有1500万行。我必须将所有这些行移植到Oracle数据库。以下是我要做的:

  1. 我读取DataTable中的行(行用逗号分隔,以便它们形成列)。我通过StreamReader阅读了这些行,并将其放入使用,以便在完成阅读后将其清除
  2. 我在DataTable中放入了一个计数器,每读取一行,计数器就会增加1
  3. 当计数器达到40.000时,我在OracleBulkCopy的帮助下将所有行导入数据库
  4. 当导入完成时,我说:

    bulkCopier.Dispose();
    dataTable.Dispose();

然而,这对任何方式都没有帮助。在任务管理器中,我看到内存使用量在增长,直到内存不足。现在我的问题是Dispose()方法不会立即释放内存吗?如果是这样,那么为什么内存使用量会累积,就好像所有DataTable和OracleBulkCopy对象都在保留内存一样。

Dispose()不会阻止内存不足异常

Dispose不会立即释放托管内存。当您调用Dispose时,Dispose会释放对非托管资源(如内存)的任何锁,并且与托管内存无关。

您的数据表全部由托管内存中的托管对象填充。调用。处理它不会有多大作用。您需要从DataTable中清除所有数据(有一种方便的Clear方法可以做到这一点),这将允许垃圾收集器在未来某个时间点释放内存,因为它感觉像是在清理东西。

使用探查器,您可以查看程序中所有内存的确切存放位置。很可能还有许多其他托管对象被您持有引用,这防止了它们被垃圾收集。这与Dispose无关。

不,dispose发出内部句柄被拆除的信号。具有Dispose的对象实际上稍后会得到GC-d。

根据使用后自动发布的文档,如果这些IDisposable,您应该尝试在using()块中使用它们。

你可以用GC.Collect强制GC收集,但我不认为那些对象是未解冻的grabage,.NET比这更好。

你能不创建一个小型转储并检查什么东西被卡住了吗?为什么?

现在我的问题是Dispose()方法是否释放内存立即

不一定。它将释放的唯一内存是非托管资源分配的内存量。它对托管堆没有任何影响。

您需要做的是确保没有引用这些悬空的DataTable实例。您可能需要从集合中删除它们,或者根据需要从变量引用中删除null