Class_Terminate不在表单上触发对象 [英] Class_Terminate not firing on object from form

查看:81
本文介绍了Class_Terminate不在表单上触发对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个非常简单的表单,它使用一个非常简单的类来处理某些事情.并且该类具有一个Class_Terminate子项,可在其自身之后进行清理.但是,关闭表单后似乎并没有触发.

I have a very simple form, that uses a very simple class to handle some things. And that class has a Class_Terminate sub to clean up after itself. However, that doesn't seem to be firing when the form gets closed.

MCVE:

Form Form1,一个名为Text0的文本框,没有其他控件

Form Form1, one text box named Text0, no further controls

Private myClass1 As Class1

Private Sub Form_Load()
    Set myClass1 = New Class1
    myClass1.InitForm Me
End Sub

Class Class1

Class Class1

Public theForm As Form
Private WithEvents SomeTextbox As TextBox
Public Sub InitForm(frm As Form)
    Set theForm = frm
    Set SomeTextbox = frm.Text0
End Sub
Private Sub Class_Terminate()
    MsgBox "Class1 terminated succesfully"
End Sub

但是,当我关闭表单时,类终止处理程序不会触发.

However, the class terminate handler doesn't fire when I close the form.

我尝试取消该类中的 Form 对象:

I tried unsetting the Form object in the class:

Private Sub Form_Unload(Cancel As Integer)
    Set myClass1.theForm = Nothing
End Sub

但是随之而来的是混乱:类终止处理程序在关闭表单后触发,但是之后立即访问而没有任何错误消息!

But chaos ensued: The class terminate handler fires after closing the form, but immediately afterwards Access hard-crashes without any error message!

推荐答案

关闭表单时,Access无法正常清理表单对象.

Access doesn't gracefully clean up the form object when you close a form.

这意味着:如果对象具有对表单的开放引用,则该表单对象将保留.如果没有引用,则只能由垃圾收集器将其删除.

That means: if an object has open references to a form, the form object persists. It only can get removed by the garbage collector if there are no references to it.

表单的第一个版本正在造成内存泄漏:表单对象Form_Form1引用了Class1(通过MyClass1变量),Class1引用了theForm变量.这导致了参考循环.终止处理程序不会触发,因为该类从未终止,它会无限期地保留在内存中,并且关闭并重新打开该表单只是打开了该类的新实例.

The first version of the form was creating a memory leak: the form object Form_Form1 had a reference to Class1 (through the MyClass1 variable), Class1 had a reference to the form object through the theForm variable. This caused a reference loop. The terminate handler didn't fire because the class never terminated, it remained in memory indefinitely, and closing and reopening the form just opened up a new instance of the class.

第二个版本引起了一个问题:当引用循环中断时,首先释放对Form1的引用(因为在Form1上仍然存在对Class1的引用),导致垃圾收集器将其清理干净,然后释放对Class1的引用,并且垃圾收集器试图清理Class1,包括文本框对象SomeTextbox,由于已清除了表单对象并且文本框对象无效,因此导致对硬崩溃的访问.

The second version caused a problem: while the reference loop was broken, references to Form1 were released first (because there still was a reference to Class1 on Form1), causing the garbage collector to clean that up, then references to Class1 were released and the garbage collector tried to clean up Class1, including the textbox object SomeTextbox, causing Access to hard-crash since the form object was already cleaned up and the textbox object was invalid.

解决方案是通过首先删除对Class1的所有引用来打破引用循环.这不会导致崩溃.

The solution is to break the reference loop by removing all references to Class1 first. This doesn't cause crashes.

Private Sub Form_Unload(Cancel As Integer)
    Set myClass1 = Nothing
End Sub

这将导致垃圾收集器首先清理Class1实例,释放对Text0的引用,然后清理表单对象,因为没有人对此有开放的引用.

This causes the garbage collector to clean up the Class1 instance first, releasing references to Text0, then cleans up the form objects because no-one has open references to that.

这篇关于Class_Terminate不在表单上触发对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆