Когда и где вызывать RemoveHandler в VB.NET? - PullRequest
1 голос
/ 27 апреля 2010

Я работаю с проектами VB.NET для Windows Forms в .NET 1.1. И у меня есть этот тип архитектуры, очень упрощенный.

Public MustInherit Class BaseTestLogic

  Private _TimerPoll As Timer

  Public Sub New(ByVal sym As SymbolFileMng, ByVal cfg As LampTestConfig, ByVal daas As DaasManager, ByVal mcf As Elux.Wg.Lpd.MCFs.VMCF)

    AddHandler _TimerPoll.Tick, AddressOf TimerPoll_Tick

  End Sub

End Class

Public Class SpecificTestLogic
  Inherits BaseTestLogic      

End Class

В зависимости от типа теста, который я делаю, я создаю экземпляр конкретного теста, полученного из BaseTestLogic . Но я обнаружил, что после сотен созданий объектов я могу получить исключение StackOverflow .

Я проверил свой код и увидел, что забыл удалить обработчик Timer Tick. Вопрос в том, где и когда правильно удалить хадлера?

Нужно ли реализовать интерфейс IDisposable в базовом классе и RemoveHandler в Dispose ?

Ответы [ 5 ]

0 голосов
/ 25 марта 2015

Это старый вопрос, но я пришел к нему через веб-поиск, поэтому он все еще полезен для таймеров. Не был дан надлежащий ответ на Вашу ОСНОВНУЮ проблему. На ваш вопрос были предложены ответы, но вопрос был неверным. Ваш вопрос должен быть: Как отключить таймер, чтобы событие больше не срабатывало?

Dim WithEvents timer1 как новый таймер ()

(затем добавьте timer1_Elapsed к вашему коду)

Это решает проблему беспокойства по поводу IDisposable или Finalize, потому что обработчик событий Timer управляется для вас. Когда вам больше не нужен таймер, установите Enabled = False или вызовите метод Stop (), чтобы он не тикал.

0 голосов
/ 23 июля 2010

Странно, но в моем случае финализатор никогда не вызывается, в чем может быть причина?

Или GC.SupressFinalize () был вызван где-то в вашем коде?

0 голосов
/ 27 апреля 2010

Вы можете согласиться с удалением обработчика при вызове Dispose, но пурист скажет, что «вы не должны злоупотреблять IDisposable в целях, отличных от удаления неуправляемых ресурсов».

Другим вариантом является удаление обработчика в методе Finalize .

Вы также можете спокойно удалить обработчик в нескольких местах, если это имеет смысл в вашем дизайне. Удаление уже удаленного обработчика не вызовет никаких проблем - если событие не является пользовательским событием и его реализации AddHandler / RemoveHandler не соответствуют поведению нестандартных событий (то есть просто использовать [Delegate] .CombineDelegate / [Delegate] .Удалить). Только не говорите своим друзьям-пуристам об этом; они не будут соответствовать.

0 голосов
/ 28 апреля 2010

Сначала я подумал, что ваша настоящая проблема имеет мало общего с добавлением и удалением обработчиков событий. StackOverflowException означает, что у вас есть ряд функций, которые создают бесконечный цикл рекурсивных вызовов. Размещенный вами код нигде не показывает, что может произойти, но трассировка стека исключения должна указывать на код, вызывающий сбой.

На основании вашего комментария о создании теста производного типа, я хотел бы знать, не могли бы вы опубликовать больше кода из конструктора в вашем базовом классе.

0 голосов
/ 27 апреля 2010

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

Вот вопрос с информацией о том, когда вам нужно беспокоиться об их удалении
AddHandler / RemoveHandler неправильно утилизируются

...