我已经在 VB.NET 中搜索了有关使用关键字句柄而不是AddHandler的区别,但我无法解释为什么这段代码不起作用。
Imports System.Threading
Public Class MyClass_EventArgs
Inherits System.EventArgs
End Class
Public Class MyClass
Public Event MainThreadFinished(ByVal sender As Object, ByVal e As MyClass_EventArgs)
Private WithEvents MyEvents As MyClass
Private trd As Thread
Public Sub New()
'AddHandler MainThreadFinished, AddressOf Me.MyEvents_ThreadFinished
trd = New Thread(AddressOf mainThread)
trd.IsBackground = True
trd.Start()
RaiseEvent MainThreadFinished(Me, Nothing)
End Sub
Protected Overrides Sub Finalize()
trd.Abort()
End Sub
Protected Sub MyEvents_ThreadFinished(ByVal sender As Object, ByVal e As MyClass_EventArgs) _
Handles MyEvents.MainThreadFinished
MessageBox.Show("AAA")
End Sub
Private Sub mainThread()
RaiseEvent MainThreadFinished(Me, Nothing)
End Sub
End Class
好吧,这段代码从不响应事件,但是如果我取消注释以下行,代码就可以工作并且会出现消息框......
'AddHandler MainThreadFinished, AddressOf Me.MyEvents_ThreadFinished
为什么会这样?
看来你已经有了很好的发现!根据Microsoft文档,RaiseEvent Statement,
不应在 在其中声明它们的类。虽然此类事件不会导致 运行时错误,关联事件可能无法捕获它们 处理器。如果需要,请使用
Shared
修饰符创建共享事件 从构造函数引发事件。
换句话说,Microsoft说你不应该做你正在做的事情 - 如果你必须,使用共享事件。
在查看其他来源时,我会说AddHandler
和Handles
之间的区别是句法糖的问题。你可能想要了解事件在 C# 中的完成方式,以便更深入地了解(例如在 C# 事件中)。 Handles
与 WithEvents
结合使用,作为类实例自动订阅事件的一种方式(否则,在 C# 中使用 +=
显式订阅事件,在 VB.NET 中使用 AddHander
显式订阅事件)。
似乎您的显式AddHandler
可确保事件连接在RaiseEvent
之前就位,因此它可以按您想要的方式工作。我只能猜测,如果没有它,这些事件连接还没有完成 - 也就是说,它不起作用,因为编译器在幕后插入了等效于 AddHandler 的代码,无论编译器编写者认为合适的设计模式。鉴于他们对此的警告,设计师似乎很清楚这种可能的后果。