我正在使用.NET 1.1中的VB.NET windows forms projet。我有这种类型的架构,非常简化。
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。问题是,删除hadler的地点和时间是否正确?
我是否需要在基类中实现 IDisposable 接口,在 Dispose 中实现RemoveHandler?
答案 0 :(得分:0)
如果你在构造函数中添加它们,那么在Dispose中删除它们是正确的,但它当然取决于你的设计。
这是一个问题,提供有关何时需要担心删除它们的信息 AddHandler/RemoveHandler Not Disposing Correctly
答案 1 :(得分:0)
您可以在调用Dispose时同时删除处理程序,但是纯粹主义者会说“除了处理非托管资源之外,您不应该滥用IDisposable”。
另一种选择是在 Finalize 方法中删除处理程序。
如果在您的设计中有任何意义,您也可以放心在几个不同的地方删除处理程序。删除已删除的处理程序不会导致任何问题 - 除非事件是自定义事件且其AddHandler / RemoveHandler实现与非自定义事件的行为不匹配(这只是使用[Delegate] .CombineDelegate / [Delegate]) 。去掉)。只是不要告诉你的纯粹朋友;他们不会遵守。
答案 2 :(得分:0)
这是一个老问题,但我是通过网络搜索来实现的,所以它仍然是一个关于计时器的有用问题。对您的问题没有给出适当的答案。答案提供给您的问题,但问题是错误的。您的问题应该是:如何禁用计时器,以便不再触发事件?
Dim WithEvents timer1作为新的Timer()
(然后将timer1_Elapsed添加到您的代码中)
这解决了担心IDisposable或Finalize的问题,因为为您管理了Timer事件处理程序。当您不再需要计时器时,请设置Enabled = False或调用Stop()方法以防止它滴答作响。
答案 3 :(得分:0)
Timer
类设计器实现 IDisposable
的决定必须被视为一种声明,即实现处理对非 .NET 的某种形式的引用API / raw 操作系统资源分配(抱歉非规范面额)。
正如@supercat 所提到的,只要事件发布者存在,事件订阅者就会一直保持活动状态,这会导致引用更大生命周期对象的问题,如 In vb.net, if I use AddHandler, Do I have to use RemoveHandler? 中所述,并且 不是,因为事件处理程序是非托管资源。
事件处理程序不是在 .NET
术语中使用的意义上的“非托管资源”,而不是“托管”:不需要通过显式分配管理Finalize
或 Dispose()
用于资源释放和清理。
来自 Troelsen 2010 Pro C#:
<块引用>终结器可以用来释放
垃圾收集器启动时的非托管资源。 然而,
鉴于许多非托管对象是“宝贵的项目”(例如原始
数据库或文件句柄),尽快释放它们可能很有价值
尽可能而不是依赖垃圾收集来发生。作为
替代覆盖 Finalize()
,您的类可以实现
IDisposable
接口,它定义了一个名为
Dispose()
。
勘误表:见Is unwired event a memory leak?
因此,回到问题,如果 TimerPoll_Tick
事件处理程序属于更大的生命周期对象,则永远不会释放 BaseTestLogic
实例。我不确定,但即使 TimerPoll_Tick
是 BaseTestLogic
静态方法,也可能会发生这种情况。
回到问题,stackoverflow 异常似乎很奇怪,可能与 TimerPoll_Tick
事件处理中的某种形式的设计失败有关,而不是与 @GideonEngelberth 建议的对象生命周期问题有关。
答案 4 :(得分:-1)
我的第一个想法是,您的实际问题与添加和删除事件处理程序几乎没有关系。 StackOverflowException意味着您有一系列函数正在创建无限循环的递归调用。您发布的代码并未显示可能发生的任何地方,但异常的堆栈跟踪应指向违规代码。
根据您关于创建派生类型测试的评论,我想知道您是否可以从基类中的构造函数发布更多代码。
答案 5 :(得分:-1)