我决定在这样的论坛上寻求帮助,因为经过几个月的努力,我无法找到解决问题的方法.
这可以被描述为“为什么即使在GC被强制启动时GC也不会释放在VB.net中创建的对象?”
请考虑以下代码.显然我的项目要复杂得多,但我能够找出问题所在:
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,可下载的试用版本here).有一个名为“调查内存泄漏”的部分.当我在“实时”标签上看到这个时,我感到非常惊讶.如果我是正确的,这个图形告诉我在代码上创建的对象都没有实际发布:
当我看到其他屏幕时,惊喜甚至更大.据此,所有未处理的对象都是System.Transactions类型,我假设它们是在.Net库中内部管理的,因为我没有在我的代码上创建这种类型的任何对象.这是否意味着VB.net标准库上有一个错误???:
请注意,在我的代码中,我没有执行任何查询.如果我这样做,ODBCDataReader对象也不会被释放,即使我调用.Close()方法(令人惊讶的是,此类型的未发布对象的数量与System.Transactions类型的未发布对象完全相同)
另一个重要的是语句GC.Collect().内存分析器使用它来刷新要显示的信息.如果您从代码中删除它,分析器将无法正确更新实时图表,给您错误的印象,即一切正确.
最后,如果你省略了connex.Open()语句,屏幕截图#1将呈现一条扁平线(这意味着所有创建的对象都已成功发布),但不幸的是,如果是,我们无法对数据库进行任何查询.连接尚未打开.
有人可以找到对此的逻辑解释,以及有效释放对象的解决方法吗?
谢谢所有人.
尼科