Ручки против AddHandler - PullRequest
       38

Ручки против AddHandler

1 голос
/ 12 сентября 2008

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

Поможет ли ручное отключение обработчиков гарантировать, что на удаленном объекте не осталось ссылки?

Ответы [ 7 ]

3 голосов
/ 12 сентября 2008

Я почти уверен, что предложение 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 закончился так:

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

2 голосов
/ 11 октября 2013

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

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

2 голосов
/ 12 сентября 2008

Это не вопрос использования AddHandler по сравнению с Handles.

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

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

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

1 голос
/ 16 сентября 2008

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

1 голос
/ 12 сентября 2008

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

0 голосов
/ 12 сентября 2008

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

0 голосов
/ 12 сентября 2008

Большую часть времени фреймворк заботится об этом за вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...