首先,提前感谢您的帮助。
我决定在这样的论坛上寻求帮助,因为经过几个月的努力,我找不到解决问题的方法。
这可以描述为'为什么在VB.net中创建的对象即使在强制启动GC时也没有被GC释放?"
请考虑以下代码。显然我的项目要复杂得多,但我能够隔离问题:
Imports System.Data.Odbc
Imports System.Threading
Module Module1
Sub Main()
'Declarations-------------------------------------------------
Dim connex As OdbcConnection 'Connection to the DB
Dim db_Str As String 'ODBC connection String
'Sentences----------------------------------------------------
db_Str = "My ODBC connection String to my MySQL database"
While True
'Condition: Infinite loop.
connex = New OdbcConnection(db_Str)
connex.Open()
connex.Close()
'Release created objects
connex.Dispose()
'Force the GC to be launched
GC.Collect()
'Send the application to sleep half a second
System.Threading.Thread.Sleep(500)
End While
End Sub
End Module
这模拟了与 MySQL 数据库建立连接的多线程应用程序。如您所见,连接被创建为一个新对象,然后被释放。最后,GC被迫启动。我已经在几个论坛以及 MSDN 在线帮助中看到过这个算法,所以就我而言,我没有做错任何事情。
当应用程序启动时,问题就开始了。创建的对象在代码中处理,但一段时间后,可用内存耗尽,应用程序崩溃。
当然,这个问题在这个小版本中很难看到,但在实际项目中,应用程序很快就会耗尽内存(由于长时间建立的连接量),因此正常运行时间只有两天. 然后我需要再次重新启动应用程序。
我在我的机器上安装了一个内存分析器(Scitech .Net Memory profiler 4.5,可 在此处下载试用版)。有一个名为“调查内存泄漏”的部分。当我在“实时”选项卡上看到这个时,我感到非常惊讶。如果我是正确的,这张图告诉我在代码上创建的所有对象都没有被实际释放:
当我看到另一个屏幕时,惊喜就更大了。据此,所有未处理的对象都是System.Transactions类型,我假设它是在 .Net 库中内部管理的,因为我没有在我的代码上创建任何这种类型的对象。这是否意味着 VB.net 标准库存在错误???:
请注意,在我的代码中,我没有执行任何查询。如果这样做,即使我调用.Close()方法,也不会释放ODBCDataReader对象(令人惊讶的是,这种类型的未释放对象的数量与System.Transactions类型的未释放对象的数量完全相同)
另一个重要的事情是声明GC.Collect()。内存分析器使用它来刷新要显示的信息。如果您从代码中删除它,分析器将不会正确更新实时图表,从而给您一种一切都正确的错误印象。
最后,如果你省略connex.Open()语句,截图 #1 将呈现一条平线(这意味着所有创建的对象都已成功释放),但不幸的是,如果我们无法对数据库进行任何查询,如果连接尚未打开。
有人可以找到对此的合乎逻辑的解释,以及有效释放对象的解决方法吗?
谢谢大家。
尼科