【问题标题】:Difference between WithEvents (Handles) vs AddHandlerWithEvents(句柄)与 AddHandler 之间的区别
【发布时间】:2012-04-12 12:43:27
【问题描述】:

我在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

为什么会这样?

【问题讨论】:

  • 你正在尝试监听你的 own 事件。没有意义,一些 other 类会对您的活动感兴趣。 vb 编译器只实现了 Handles 的合理使用。如果需要这种模式,请使用虚拟方法。
  • 是的,你是对的,这不是一个好的实现,但我写这个是为了测试事件系统。

标签: vb.net event-handling


【解决方案1】:

看来您的发现不错!根据 Microsoft 文档,RaiseEvent Statement

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

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

在查看其他来源时,我想说AddHandlerHandles 之间的区别在于语法糖。您可能想了解事件在 C# 中是如何完成的,以获得更深入的了解(例如在 C# Events 中)。 HandlesWithEvents 结合使用,作为类实例自动订阅事件的一种方式(否则,在 C# 中使用 += 和在 VB.NET 中使用 AddHander 显式完成)。

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

【讨论】:

  • 嘿伙计,你知道有什么好的资源可以找到这样好的内容吗?我发现很难理解 VB.net 中必须使用 WithEvents、RaiseEvents、AddHandler 和其他东西的事件。我要做的是通过单击一个按钮将数据从一个用户控件的文本框传输到另一个用户控件,但我找不到任何可以证明这一点的教程。
  • @Carnal:事件只是实现“回调”的另一种方式(en.wikipedia.org/wiki/Callback_(computer_programming))。这是让您的班级与其他班级互动的一种方式。您在类中定义事件,并且在类中的关键或有趣的点,您的代码使用RaiseEvent 让其他类响应那些关键或有趣的时刻。其他类订阅您类中定义的任何事件,自动(WithEventsHandles)或显式(AddHandler)。
  • @Carnal:订阅的意思是:其他一些类将Delegate(函数指针的.NET等价物)传递给您的类,用于您的类中定义的特定事件;这个代表将是另一个班级的FunctionSub。当您的班级执行RaiseEvent 的事情时,它将调用其他班级传递给它的每个Delegate。当有多个代表时,它会依次调用每个代表,一次一个(可能以任意顺序)。当没有代表时,什么都不会发生。
猜你喜欢
  • 2010-09-08
  • 1970-01-01
  • 2014-10-22
  • 1970-01-01
  • 2011-01-13
  • 1970-01-01
  • 2012-09-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多