Class_Terminate не стреляет по объекту из формы - PullRequest
0 голосов
/ 26 октября 2018

У меня очень простая форма, которая использует очень простой класс для обработки некоторых вещей. И этот класс имеет подпрограмму Class_Terminate для очистки после себя. Однако, похоже, что это не срабатывает, когда форма закрывается.

MCVE:

Форма Form1, одно текстовое поле с именем Text0, больше никаких элементов управления

Private myClass1 As Class1

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

Класс 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

Однако обработчик завершения класса не срабатывает при закрытии формы.

Я попытался удалить объект Форма в классе:

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

Но последовал хаос: обработчик завершения класса срабатывает после закрытия формы, но сразу после этого получает доступ к сбоям без сообщений об ошибках!

1 Ответ

0 голосов
/ 26 октября 2018

Access не изящно очищает объект формы при закрытии формы.

Это означает: если объект имеет открытые ссылки на форму, объект формы сохраняется. Он может быть удален сборщиком мусора, только если на него нет ссылок.

Первая версия формы создавала утечку памяти: объект формы Form_Form1 имел ссылку на Class1 (через переменную MyClass1), Class1 имел ссылку на объект формы через theForm переменная. Это вызвало цикл ссылок. Обработчик завершения не сработал, потому что класс никогда не завершался, он оставался в памяти на неопределенный срок, а закрытие и повторное открытие формы просто открыло новый экземпляр класса.

Вторая версия вызвала проблему: в то время как ссылочный цикл был прерван, ссылки на Form1 были выпущены первыми (потому что все еще была ссылка на Class1 на Form1), в результате чего сборщик мусора очистил это затем ссылки на Class1 были освобождены, и сборщик мусора попытался очистить Class1, включая объект текстового поля SomeTextbox, что привело к аварийному завершению Access, поскольку объект формы уже был очищен, а объект текстового поля недействителен.

Решение состоит в том, чтобы разорвать цикл ссылок, удалив сначала все ссылки на Class1. Это не вызывает сбоев.

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

Это приводит к тому, что сборщик мусора сначала очищает экземпляр Class1, освобождая ссылки на Text0, а затем очищает объекты формы, потому что никто не имеет открытых ссылок на это.

...