首先,预先感谢你的帮助。
几个月的艰苦工作后,我决定在像这样的论坛上寻求帮助,因为我找不到解决我的问题的方法。
这可以描述为“为什么在VB.net中创建的对象在释放时即使强制启动GC,也不会被GC释放?”
请考虑以下代码片段。显然,我的项目要复杂得多,但是我能够隔离出问题:
这是模拟一个多线程应用程序与MySQL数据库建立连接的过程。可以看到连接是作为新对象创建,然后释放掉。最后,强制启动了GC。我在几个论坛以及MSDN在线帮助中都看到了这个算法,因此就我而言,我没有做错任何事情。
问题出现在应用程序启动时。虽然在代码中已经释放了创建的对象,但是过一段时间后,可用内存被耗尽,导致应用程序崩溃。
当然,在这个小版本中很难看出这个问题,但是在实际项目中,由于随着时间推移建立的连接数量增加,应用程序很快就会耗尽内存,结果只能运行两天。然后我需要再次重启应用程序。
我在我的机器上安装了一个内存分析工具(Scitech .Net Memory profiler 4.5,可从此处下载试用版),其中有一个名为“调查内存泄漏”的部分。当我在“实时”选项卡上看到这个图形时,我感到非常惊讶。如果我没记错的话,这个图示告诉我,代码中创建的所有对象都没有被释放:
(插入了一张图片)
当我看到这张图片时,我的惊讶甚至更大了。根据这个图示,所有未释放的对象都是System.Transactions类型,我认为这些对象在.NET库中被内部管理,因为我没有在代码中创建任何这种类型的对象。这是否意味着VB.net标准库中存在一个bug???
(再插入一张图片)
请注意,在我的代码中,我没有执行任何查询。如果我这样做的话,即使调用.Close()方法,ODBCDataReader对象也不会被释放(令人惊讶的是,这种类型的未释放对象数量与类型System.Transactions的未释放对象数量完全相同)。
另一个重要的事情是声明GC.Collect()。这是内存分析工具用来刷新要显示的信息的。如果你从代码中删除它,分析器将无法正确更新实时图,给你错误的印象,认为一切都正确。
最后,请注意如果省略 connex.Open() 语句,则截图#1将呈现平坦的线条(这意味着所有已创建的对象都已成功释放),但不幸的是,如果连接未打开,我们就无法对数据库进行任何查询。
有人能找到一个合乎逻辑的解释,并有效地释放对象吗?谢谢大家。
几个月的艰苦工作后,我决定在像这样的论坛上寻求帮助,因为我找不到解决我的问题的方法。
这可以描述为“为什么在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标准库中存在一个bug???
(再插入一张图片)
请注意,在我的代码中,我没有执行任何查询。如果我这样做的话,即使调用.Close()方法,ODBCDataReader对象也不会被释放(令人惊讶的是,这种类型的未释放对象数量与类型System.Transactions的未释放对象数量完全相同)。
另一个重要的事情是声明GC.Collect()。这是内存分析工具用来刷新要显示的信息的。如果你从代码中删除它,分析器将无法正确更新实时图,给你错误的印象,认为一切都正确。
最后,请注意如果省略 connex.Open() 语句,则截图#1将呈现平坦的线条(这意味着所有已创建的对象都已成功释放),但不幸的是,如果连接未打开,我们就无法对数据库进行任何查询。
有人能找到一个合乎逻辑的解释,并有效地释放对象吗?谢谢大家。