Есть ли преимущество для динамического прикрепления/снятия обработчиков событий?Ручки против AddHandler
Удалили бы ручные устройства вручную, чтобы убедиться, что ссылка на объект не указана?
Есть ли преимущество для динамического прикрепления/снятия обработчиков событий?Ручки против AddHandler
Удалили бы ручные устройства вручную, чтобы убедиться, что ссылка на объект не указана?
Речь идет не об использовании AddHandler и Handles.
Если вас беспокоит ссылка на ваш обработчик событий, мешающий сбору мусора, вы должны использовать RemoveHandler, независимо от того, как был прикреплен обработчик. В методе Dispose или в элементе управления удалите все обработчики.
У меня были ситуации в приложениях Windows Forms (.NET 1.1 дней), где обработчик событий будет вызываться на элементах управления, у которых не было других ссылок на них (и которые по сути были мертвы, и я бы подумал, что это GC'ed) - чрезвычайно сложно отлаживать.
Я бы использовал RemoveHandler, чтобы избавиться от обработчиков на элементах управления, которые вы не собираетесь использовать повторно.
В большинстве случаев структура заботится об этом для вас.
Ручное отключение события может быть важным для предотвращения утечек памяти: объект, который подключается к событию, запущенному другим объектом, не будет собирать мусор, пока объект, который запускает событие, не будет собран с мусором. Другими словами, «event-raiser» имеет сильную ссылку на все связанные с ним «события-слушатели».
Я нахожу, что динамическое прикрепление/отсоединение обработчиков событий используется только там, где у вас есть долгоживущий объект, выдает события, которые потребляются многими недолговечными объектами. Для большинства других случаев два объекта расположены примерно в одно и то же время, и CLR выполняет достаточную работу по очистке самостоятельно
Я уверен, что статья Handles
является просто синтаксическим сахаром и вставляет в ваш текст заявление AddHandler
конструктор. Я проверял с помощью этого кода и отключил структуру приложения, чтобы конструктор не будет иметь дополнительный материал:
Public Class Form1
Public Sub New()
' This call is required by the Windows Form Designer. '
InitializeComponent()
' Add any initialization after the InitializeComponent() call. '
AddHandler Me.Load, AddressOf Form1_Load
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim breakpoint As Integer = 4
End Sub
End Class
Ил кончался так:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: call instance void [System.Windows.Forms]System.Windows.Forms.Form::.ctor()
IL_0007: nop
IL_0008: ldarg.0
IL_0009: ldarg.0
IL_000a: dup
IL_000b: ldvirtftn instance void WindowsApplication1.Form1::Form1_Load(object,
class [mscorlib]System.EventArgs)
IL_0011: newobj instance void [mscorlib]System.EventHandler::.ctor(object,
native int)
IL_0016: call instance void [System.Windows.Forms]System.Windows.Forms.Form::add_Load(class [mscorlib]System.EventHandler)
'... lots of lines here '
IL_0047: ldarg.0
IL_0048: callvirt instance void WindowsApplication1.Form1::InitializeComponent()
IL_004d: nop
IL_004e: ldarg.0
IL_004f: ldarg.0
IL_0050: dup
IL_0051: ldvirtftn instance void WindowsApplication1.Form1::Form1_Load(object,
class [mscorlib]System.EventArgs)
IL_0057: newobj instance void [mscorlib]System.EventHandler::.ctor(object,
native int)
IL_005c: callvirt instance void [System.Windows.Forms]System.Windows.Forms.Form::add_Load(class [mscorlib]System.EventHandler)
IL_0061: nop
IL_0062: nop
IL_0063: ret
} // end of method Form1::.ctor
Обратите внимание на два идентичных блоков кода вокруг IL_000b и IL_0051. Я думаю, что это просто синтаксический сахар.
Я вручную прикрепляю обработчики, когда вручную создаю элементы управления (например, динамически создавая TextBox для каждой записи базы данных). Я вручную отсоединяю обработчиков, когда они обрабатывают вещи, которые я еще не совсем готов обрабатывать (возможно, потому, что я использую неправильные события? :))
Объявление поля как WithEvents
приведет к тому, что компилятор автоматически сгенерирует свойство с этим именем. Получатель возвращает значение поля поддержки. Устроитель немного сложнее. Сначала он проверяет, имеет ли поле подкрепления правильное значение. Если это так, оно завершается. В противном случае, если поле поддержки не равно null, оно выдает запросы «RemoveHandler» для всех своих событий объекту, указанному в поле поддержки. Затем, независимо от того, было ли поле поддержки ненулевым, оно устанавливает его равным запрашиваемому значению. Наконец, если новое значение не является нулевым, то был ли старый или нет, свойство «AddHandler» вызывает запросы для всех своих событий для объекта, идентифицированного новым значением.
При условии, что каждый из элементов объекта WithEvents объекта до Nothing
перед тем, как отказаться от него, и избегает манипулирования членами WithEvents в нескольких потоках, автоматически генерируемый код события не будет течь.