2008-09-11 6 views
1

Есть ли преимущество для динамического прикрепления/снятия обработчиков событий?Ручки против AddHandler

Удалили бы ручные устройства вручную, чтобы убедиться, что ссылка на объект не указана?

ответ

2

Речь идет не об использовании AddHandler и Handles.

Если вас беспокоит ссылка на ваш обработчик событий, мешающий сбору мусора, вы должны использовать RemoveHandler, независимо от того, как был прикреплен обработчик. В методе Dispose или в элементе управления удалите все обработчики.

У меня были ситуации в приложениях Windows Forms (.NET 1.1 дней), где обработчик событий будет вызываться на элементах управления, у которых не было других ссылок на них (и которые по сути были мертвы, и я бы подумал, что это GC'ed) - чрезвычайно сложно отлаживать.

Я бы использовал RemoveHandler, чтобы избавиться от обработчиков на элементах управления, которые вы не собираетесь использовать повторно.

0

В большинстве случаев структура заботится об этом для вас.

0

Ручное отключение события может быть важным для предотвращения утечек памяти: объект, который подключается к событию, запущенному другим объектом, не будет собирать мусор, пока объект, который запускает событие, не будет собран с мусором. Другими словами, «event-raiser» имеет сильную ссылку на все связанные с ним «события-слушатели».

1

Я нахожу, что динамическое прикрепление/отсоединение обработчиков событий используется только там, где у вас есть долгоживущий объект, выдает события, которые потребляются многими недолговечными объектами. Для большинства других случаев два объекта расположены примерно в одно и то же время, и CLR выполняет достаточную работу по очистке самостоятельно

3

Я уверен, что статья 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. Я думаю, что это просто синтаксический сахар.

1

Я вручную прикрепляю обработчики, когда вручную создаю элементы управления (например, динамически создавая TextBox для каждой записи базы данных). Я вручную отсоединяю обработчиков, когда они обрабатывают вещи, которые я еще не совсем готов обрабатывать (возможно, потому, что я использую неправильные события? :))

1

Объявление поля как WithEvents приведет к тому, что компилятор автоматически сгенерирует свойство с этим именем. Получатель возвращает значение поля поддержки. Устроитель немного сложнее. Сначала он проверяет, имеет ли поле подкрепления правильное значение. Если это так, оно завершается. В противном случае, если поле поддержки не равно null, оно выдает запросы «RemoveHandler» для всех своих событий объекту, указанному в поле поддержки. Затем, независимо от того, было ли поле поддержки ненулевым, оно устанавливает его равным запрашиваемому значению. Наконец, если новое значение не является нулевым, то был ли старый или нет, свойство «AddHandler» вызывает запросы для всех своих событий для объекта, идентифицированного новым значением.

При условии, что каждый из элементов объекта WithEvents объекта до Nothing перед тем, как отказаться от него, и избегает манипулирования членами WithEvents в нескольких потоках, автоматически генерируемый код события не будет течь.