1

我有一个问题,我的 .NET 3.5 应用程序导致 IIS 工作进程不断消耗内存并且永远不会释放它,直到应用程序开始抛出与内存相关的错误并且我必须回收 IIS 工作进程。我注意到的另一件事是,与 Oracle DB 服务器的连接也不会关闭,并且会保持打开状态,直到我回收 IIS 工作进程(据我所知,我正在正确关闭 Oracle 连接)。从我在其他类似帖子中读到的内容来看,GC 应该清理未使用的内存并允许重新分配它,但这显然不会在这里发生(我在远程主机和本地主机上都观察到同样的问题。我将假设这不是与 IIS 设置相关的问题,而是我没有在我的代码中进行适当的清理工作;我应该看什么?谢谢。

这是我与查询 Oracle DB 相关的代码:

 Using conn As New OracleConnection(oradb)

        Try

            cmd.Connection = conn
            daData = New OracleDataAdapter(cmd)
            cbData = New OracleCommandBuilder(daData)
            dtData = New DataTable()
            dtDADPLIs = New DataTable()
            conn.Open()

            cmd.CommandText = "SELECT * FROM TABLE" _                                       

            daData.Fill(dtData)

            cmd.CommandText = "SELECT * FROM TABLE2"

            daData.Fill(dtDADPLIs)
            QueryName = "SD_TIER_REPORT"
            WriteQueryLog(QueryName)

        Catch ex As OracleException

            'MessageBox.Show(ex.Message.ToString())

        Finally

            conn.Close()
            conn.Dispose()

        End Try
4

1 回答 1

1

一旦我遇到同样的问题,我就碰到了这篇文章这篇文章。 我与作者(Paul Wilson)交换了几封电子邮件,他帮助我理解了在“大对象堆”中分配在内存中的大对象的问题,并且它永远不会被压缩。

这是他告诉我的:

较大的对象确实是单独分配的,其中大的大约是 60-90 KB 或更大(我不记得确切,无论如何也没有正式记录)。因此,如果您的字节数组和其他对象大于该阈值,那么它们将被单独分配。什么时候收集大对象堆?您可能已经遇到过关于存在几代正常内存分配(当前框架中的 0、1 和 2)的声明——大对象堆基本上被认为是自动的第 2 代。这意味着它不会被收集,直到收集 gen 0 和 gen 1 后没有足够的内存 - 所以基本上它只发生在完整的 GC 收集上。所以回答你的问题——没有办法确保大对象堆中的对象被尽快收集。问题是我在谈论垃圾收集,它假定您的对象(在这种情况下为大对象)不再在任何地方被引用,因此可以被收集。如果它们仍然在某处被引用,那么 GC 运行多少根本就无关紧要——您的内存使用量只会不断增加。那么你的所有参考资料都消失了吗?看起来你这样做了,而且你可能是对的——我能告诉你的是,它很容易出错,而且它使用内存分析器进行了大量的工作,而且没有捷径可以证明它的一种或另一种方式。我可以告诉你,如果手动 GC.Collect 确实减少了你的内存使用量,那么你 显然,您的对象已被取消引用——否则 GC.Collect 将无济于事。所以问题可能只是是什么让你认为你有记忆问题?如果大型服务器系统上有足够的可用内存,GC 可能没有理由收集内存!

另一篇值得一读的文章是this

解决方案?

  1. 仅获取您需要的数据
  2. 尽可能避免使用数据集并选择数据阅读器。

更新:

如果您使用的是MS ReportViewer等报告工具,是否可以将报告绑定到“业务对象”。

于 2013-09-10T14:55:54.313 回答