类的对象何时释放?

WormJan 2012-10-30 08:04:43
刚才在群里有位高手说,在对象触发的事件里销毁对象不安全。那到底应该在哪里释放。我希望并不是在程序退出时释放,而是实时释放。即它触发事件后我不需要它了,然后就释放它。例如以下代码:

类的代码:
Public Event test()

Public Sub a()
RaiseEvent test
End Sub

窗体代码:
Dim WithEvents k As Class1

Private Sub Command1_Click()
Set k = New Class1
k.a
End Sub

Private Sub k_test()
MsgBox "d"
'假如这个时候,我已经不再需要k这个对象了,能否在下面释放?如果不能,那我想在触发test事件后就释放它,因为我已经不再需要它了,应该怎么释放?
Set k = Nothing
End Sub
...全文
360 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
c_cyd2008 2012-10-30
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 的回复:]
嗯。我明白了。其实这个问题是别人在讨论,我在观战。而我偏向于事件中销毁对象的做法。平时也是这么用的。因为有时候不能在程序退出时释放。需要即时释放。所以嘛。。又听牛人说在事件中销毁不安全,想想貌似也对哈这说法。感觉他们说的都有道理。一时晕乎者也了。
非常感谢2位的解答,尤其是c_cyd2008!
[/Quote]
虽然如此,但不推荐你这样做!设计异步操作时,不妨参考下Ado等的open、close方法,不用释放对象,即可释放内存
WormJan 2012-10-30
  • 打赏
  • 举报
回复
OK,非常感谢!
结贴。
c_cyd2008 2012-10-30
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]
嗯。你举的例子,看代码没有问题,但实际操作起来,有可能就会出错。尤其象我这样的小白更容易错。主要是不知道我说的这种工作流程,有没有VB不允许或不正确的地方。
[/Quote]
这个可以放心的,清楚流程你就可以做
WormJan 2012-10-30
  • 打赏
  • 举报
回复
嗯。我明白了。其实这个问题是别人在讨论,我在观战。而我偏向于事件中销毁对象的做法。平时也是这么用的。因为有时候不能在程序退出时释放。需要即时释放。所以嘛。。又听牛人说在事件中销毁不安全,想想貌似也对哈这说法。感觉他们说的都有道理。一时晕乎者也了。
非常感谢2位的解答,尤其是c_cyd2008!
c_cyd2008 2012-10-30
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]
@c_cyd2008
我明白你的意思。这个情况有点不同。k.a这个方法并不是立即返回数据。k.a会做一些异步的处理,比如会调用winsock(怎么调用咱先不管它)获取数据。我们都知道winsock是异步的,也就是说,k.a之后,事件不是马上触发,这个时候,command1_click过程结束,也许过上五秒钟,winsock完成了工作,对象k处理完善后之事,触发test事件,test事件触发后主窗……
[/Quote]
如果你清楚地知道什么候要用,什么时候不用,当然可以像你上面那么做,你也许可以参考下winsock控件的使用方法
WormJan 2012-10-30
  • 打赏
  • 举报
回复
嗯。你举的例子,看代码没有问题,但实际操作起来,有可能就会出错。尤其象我这样的小白更容易错。主要是不知道我说的这种工作流程,有没有VB不允许或不正确的地方。
WormJan 2012-10-30
  • 打赏
  • 举报
回复
类里面其实是这样的:

Public Event test(string)

Public Sub a()
要求 winsock 干活
End Sub

sub winsock_close()'winsock工作完成
处理数据,然后触发test事件
raiseevent test(数据)
end sub



窗体接收事件:
Private Sub k_test(string)
MsgBox string'看看返回了什么东西
Set k = Nothing '释放对象
End Sub


我的意思是,上面这种释放对象的方法。
这才说明白了,呵呵。
c_cyd2008 2012-10-30
  • 打赏
  • 举报
回复
比如你的类可能如下,有三个方法,分别完成某一件事
Public Event test()
Public Sub a()
RaiseEvent test
End Sub

Public Sub b()
End Sub
Public Sub c()
End Sub

一种可能的调用:
Private Sub Command1_Click()
Set k = New Class1
k.a '调用a
k.b '调用b
k.c '调用c
End Sub
Private Sub k_test()
MsgBox "d"
'假如这个时候,我已经不再需要k这个对象了,能否在下面释放?如果不能,那我想在触发test事件后就释放它,因为我已经不再需要它了,应该怎么释放?
Set k = Nothing
End Sub

如果单看上面的调用代码,几乎很难看出有什么问题
WormJan 2012-10-30
  • 打赏
  • 举报
回复
@c_cyd2008
我明白你的意思。这个情况有点不同。k.a这个方法并不是立即返回数据。k.a会做一些异步的处理,比如会调用winsock(怎么调用咱先不管它)获取数据。我们都知道winsock是异步的,也就是说,k.a之后,事件不是马上触发,这个时候,command1_click过程结束,也许过上五秒钟,winsock完成了工作,对象k处理完善后之事,触发test事件,test事件触发后主窗体接收事件,处理数据。然后完成整个工作流程。
所以只好把释放对象的活放在了k_test事件中。
c_cyd2008 2012-10-30
  • 打赏
  • 举报
回复
之所以在窗体load时创建,unload时释放,是因为考虑到在窗体整个生存期内你都可能会用到它,如果你只在某一过程内才用到它,那你就应该在这一过程内创建和释放,如你的代码:
Private Sub Command1_Click()
Set k = New Class1
k.a
Set k=Nothing '应在这里释放,不应放在k_test中
End Sub

放在k_test中不是不行,不过只会给你带来很多麻烦,特别是引用k的过程比较多时
WormJan 2012-10-30
  • 打赏
  • 举报
回复
@c_cyd2008
关于创建,这个可能何时都有可能创建,例如form_load,例如button_click,而销毁对象,如果按你第一段说的,form_load里new,就要在form_unload里释放了,这样就违背了即时释放的原则。主要考虑内存占用。按第二段说的,那么说,我在对象所触发的事件里释放这个对象,完全没有问题了是吗?即:

Private Sub k_test()
MsgBox "d"
'假如这个时候,我已经不再需要k这个对象了,能否在下面释放?如果不能,那我想在触发test事件后就释放它,因为我已经不再需要它了,应该怎么释放?
Set k = Nothing
End Sub
WormJan 2012-10-30
  • 打赏
  • 举报
回复
感谢楼上指点。但我还有点不清楚。
虽说系统有回收机制,但是如果class1会做一些比较占用内存的事情。如果不在它做完后及时nothing,占用内存就会越来越大而且很大。所以就需要在它工作完成以后,及时释放它。

从上面的例子来看,触发事件test之后,这个对象就完成了它的工作。那这个时候,由于我可能会new出多个class1对象,这些对象何时完成工作还不一定。为了减少内存占用,为了让程序长时间开着也不至于太占系统资源,所以现在需要释放 完成工作的 这个对象。

那么,代码写在对象所触发的事件里为什么那高手说不合理?如果这样,类似上面的代码,销毁的代码写在哪里呢?
c_cyd2008 2012-10-30
  • 打赏
  • 举报
回复
一般是“谁创建,谁释放”,在同一作用域内创建和释放,如同一过程内,过程的开始创建,就过程结尾释放;同一窗体内,窗体加载时创建,就窗体卸载时释放。这样做的好处是你可以清楚地知道对象什么时候可用,什么时候不可用。
当然,不在同一作用域内创建和释放也可以,但你必须清楚地知道对象什么时候可用,什么时候不可用,特别是当模块很多时!所谓“不安全”多半就是人很难记住在什么地方new了,在什么=nothing
贝隆 2012-10-30
  • 打赏
  • 举报
回复
系统有回收机制,对于程序而言你设置为Nothing就等于告诉系统,这块内存空间你可以回收了。至于系统怎么办,在下不清楚了。

值得说明的是,每个生命并实例化的对象都最好显式的设置为Nothing,不然可能会导致内存泄漏

7,763

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧