2

我在VB.NET中搜索了关于使用关键字Handles而不是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

为什么会这样?

4

1 回答 1

5

看来你有一个很好的发现!根据 Microsoft 文档,RaiseEvent 声明

不应在声明它们的类的构造函数中引发非共享事件。尽管此类事件不会导致运行时错误,但它们可能无法被关联的事件处理程序捕获。Shared如果需要从构造函数引发事件,请使用修饰符创建共享事件。

换句话说,微软说你不应该做你正在做的事情——如果必须的话,使用共享事件。

AddHandler在查看其他来源时,我会说和之间的区别Handles是句法糖的问题。您可能想了解事件在 C# 中是如何完成的,以了解更多信息(例如在C# Events中)。Handles与 with 结合使用,WithEvents作为类实例自动订阅事件的一种方式(否则+=在 C# 和AddHanderVB.NET 中显式完成)。

似乎您的明确AddHandler确保事件连接在 之前就位RaiseEvent,因此它可以按您的意愿工作。我只能猜测,如果没有这个,那些事件连接还没有完成——也就是说,它没有工作,因为编译器在幕后插入了执行相当于 AddHandler 的代码,无论编译器编写者采用什么设计模式认为合适。鉴于他们对此提出警告,设计师似乎很清楚这种可能的后果。

于 2012-04-12T14:53:36.477 回答