【发布时间】:2009-02-05 17:47:44
【问题描述】:
我总是读到,一旦我完成了对象,建议将它们设置为空。但我通常只在表单内的函数中使用它们。
无论将对象设置为Nothing,当离开函数范围时,引用是否丢失并释放内存?
即真的有必要吗:
Set db = Nothing
Set record_set = Nothing
【问题讨论】:
我总是读到,一旦我完成了对象,建议将它们设置为空。但我通常只在表单内的函数中使用它们。
无论将对象设置为Nothing,当离开函数范围时,引用是否丢失并释放内存?
即真的有必要吗:
Set db = Nothing
Set record_set = Nothing
【问题讨论】:
VB 使用所谓的“引用计数”垃圾收集器。
基本上,一旦变量超出范围,被引用对象上的引用计数器就会递减。当您将对象引用分配给另一个变量时,引用计数器会递增。
当计数器达到零时,对象已准备好进行垃圾回收。一旦发生这种情况,对象资源将被释放。函数局部变量很可能会引用一个引用计数从不高于 1 的对象,因此函数结束时将释放对象资源。
将变量设置为Nothing 是显式减少引用计数器的方法。
例如,您读入一个文件,并在调用ReadAll() 之后立即将文件对象变量设置为Nothing。文件句柄将立即释放,您可以慢慢处理其内容。
如果您未设置为 Nothing,则文件句柄的打开时间可能会超过绝对必要的时间。
如果您不是处于“必须解除对有价值资源的阻塞”的情况,只需让变量超出范围即可。
【讨论】:
垃圾收集很少是完美的。即使在 .NET 中,有时也强烈建议您提示系统尽早进行垃圾收集。
出于这个原因,当我完成它们时,我明确地同时关闭并设置为Nothing记录集。
【讨论】:
Microsoft DAO 帮助和 Access 开发人员参考中“Recordset.Close”的帮助主题的最后一行是这样的:
"Close 方法的替代方法是 设置对象变量的值 为空(设置 dbsTemp = 空)。”
http://msdn.microsoft.com/en-us/library/bb243098.aspx
考虑到这一点,来自 Microsoft 知识库的题为“How to prevent database bloat after you use Data Access Objects (DAO)”的 this article 告诉您,如果您不希望您的数据库膨胀。你会注意到这篇文章对细节有点含糊; “原因”部分不清楚,几乎到了胡言乱语的程度。
http://support.microsoft.com/kb/289562
症状:Microsoft Access 数据库 已经开始膨胀(或在 大小)在您实施数据访问之后 对象 (DAO) 打开记录集。
原因:如果您不发布 每次你记录集的内存 循环通过记录集代码,DAO 可能会重新编译,使用更多的内存和 增加数据库的大小。
更多信息:当您创建一个 Recordset(或 QueryDef)对象 代码,显式关闭对象时 你完蛋了。微软访问 自动关闭 Recordset 和 大多数下的QueryDef对象 情况。但是,如果你 明确地关闭你的对象 代码,可以避免偶尔 对象保留时的实例 打开。
最后,让我补充一点,我使用 Access 数据库已经 15 年了,而且我几乎总是让本地声明的记录集变量超出范围,而没有显式使用 Close 方法。我没有对它进行任何测试,但这似乎无关紧要。
【讨论】:
当您使用 ASP 经典(服务器端脚本)时,将所有对象设置为空是很重要的,因为它们在 [虚拟] 服务器关闭之前不会超出范围。
因此,所有 MS VB 脚本示例总是显示对象被关闭并设置为空。这样脚本摘录就可以在对象没有超出范围的环境中使用,例如 ASP 经典。
在极少数情况下,您希望编写长时间运行的进程,其中对象不会超出范围,并且如果您不显式释放对象,您会发现自己的物理内存不足。
如果您发现自己在编写 ASP 经典代码,或者出于其他原因在全局范围内运行进程,那么是的,您应该显式释放对象。
【讨论】:
当变量超出范围时,应该清理引用。据推测,该软件的更高版本已对此进行了改进,但有时它并不可靠。我认为将变量显式设置为“无”仍然是一种好习惯。
【讨论】:
我通常总是把它放在我的程序的末尾,或者如果我使用的是模块级的,则调用一个“CloseRecordSet”子:
Private Sub Rawr()
On Error GoTo ErrorHandler
'Procedural Code Here.
ExitPoint:
'Closes and Destroys RecordSet Objects.
If Not Recset Is Nothing Then
If Recset.State = 1 Then
Recset.Close
Conn.Close
End If
Set Recset = Nothing
Set Conn = Nothing
End If
Exit Sub
ErrorHandler:
'Error Handling / Reporting Here.
Resume ExitPoint
End Sub
这样程序结束,(无论是正常还是由于错误)对象被清理并且资源是空闲的。
这样做是非常安全的,因为您只需将其插入,它只会在关闭或销毁记录集/连接对象方面执行必要的操作,以防它已经关闭(由于运行时错误或只是提前关闭它,这只是确保)。
真的没有太多麻烦,而且最好在完成对象后清理它们以立即释放资源,无论程序中发生什么。
【讨论】:
试试这个
If Not IsEmpty(vMyVariant) Then
Erase vMyVariant
vMyVariant = Empty
End If
【讨论】: