当发件人是另一个类的一部分时,无法删除事件处理程序(使用RemoveHandler)的问题

时间:2019-04-18 01:54:35

标签: vb.net

我有一个系统,其中一类“自动化提供程序”正在与某些Control对象一起使用,以为它们提供一些高级监视功能(通过动态监视事件)。

我的代码的一部分;名为Automation_Provider的类包含名为Browser_Navigate的函数,该函数接受对System.Windows.Forms.WebBrowser实例的引用,并通过URL执行.Navigate操作。

它提供的特殊功能是将事件处理程序设置为Browser.DocumentCompleted,以便在引发事件时执行某些操作。

这部分实际上有效。什么是行不通的,是我试图动态删除导致首先调用Subroutine的处理程序,但它似乎并没有删除该处理程序,如果我尝试再次调用该函数,它将触发两次。

代码如下:

Public Class Automation_Functions
    Public Function Browser_Navigate(ByRef Browser As WebBrowser, ByVal Address As String) As Function_Status
        '-----------------------------------------------------------------------------------
        ' A bunch of URL checks are performed here to make sure the "Address" is a valid URL
        '-----------------------------------------------------------------------------------

        AddHandler Browser.DocumentCompleted, AddressOf Browser_Navigation_Callback
        Browser.Navigate(Address)
    End Function

    Private Sub Browser_Navigation_Callback(sender As Object, e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs)
        'Get the browser object from the sender and remove the handler that initially called this function
        Dim Browser As WebBrowser = CType(sender, WebBrowser)
        RemoveHandler Browser.DocumentCompleted, AddressOf Browser_Navigation_Callback

        '------------------------------------------------------------------------------------------
        ' A bunch of operations are performed here related to telling the caller of the original
        ' function about the performance of the web page - stuff like load time, etc.
        '------------------------------------------------------------------------------------------
    End Sub
End Class

不过,过去的处理程序从未真正从Browser_Navigation_Callback函数中删除-我知道这是因为第二次调用Browser_Navigate函数会导致Browser_Navigation_Callback函数被称为 两次 ,那么如果您第三次调用它,它会被称为 三次! -处理程序只是彼此叠加因为它们实际上从未被移除。

我一直无法找到发生这种情况的任何原因-我假设它可能与WebBrowser对象实际上在另一个类中并强制转换{ {1}}作为WebBrowser对象不会将其引用回原始WebBrowser实例,而是创建一个新实例。但是我不知道如何确认这确实是实际发生的情况,因为我在调试模式下看不到附加的事件处理程序。

除此之外-此代码应该可以正常工作。任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:0)

未设置Option Strict时,VB的功能之一是它将使用“轻松委托转换”。这意味着当委托参数与要求的签名不完全匹配但兼容时,VB会自动插入一个匿名包装程序,该包装程序将从提供的委托转换为要求的签名。

这与AddHandlerRemoveHandler产生负面互动。 VB在每个调用上创建一个新的匿名包装,并且每个实例都是不同的。实际上,这意味着使用宽松的委托转换时,不可能删除已添加的处理程序。

启用Option Strict时,将禁用宽松的委托转换,因此当委托参数与所需的签名不完全匹配时,它将变成编译器错误。我还没有找到单独的编译器开关来关闭宽松的委托转换,因此处理此问题的唯一方法是为文件打开Option Strict