我相信还有其他人可以为您提供底层 .Net 框架行为的详细解释,但结果是,通过附加事件处理程序,即使在处理该对象后,该对象仍会触发该事件。
您可以通过以下修改来证明这一点:
' Add any initialization after the InitializeComponent() call.
For i = 1 To 4
System.Threading.Thread.Sleep(10)
Using pPing As New System.Net.NetworkInformation.Ping
AddHandler pPing.PingCompleted, AddressOf pingHandler
AddHandler pPing.Disposed, AddressOf pingDisposed
pPing.SendAsync("someaddressthatmayormaynotwork.com", 10000)
End Using
Next i
GC.Collect()
Console.WriteLine("completed")
Public Sub pingHandler(sender As Object, e As System.Net.NetworkInformation.PingCompletedEventArgs)
Console.WriteLine("pingCompleted")
End Sub
Public Sub pingDisposed(sender As Object, e As System.EventArgs)
Console.WriteLine("Disposed")
End Sub
在这种情况下,如果定位 URL 或接收响应的时间过长,则 dispose 事件可以在 pingHandler 事件触发之前触发,但 pingHandler 事件将始终触发。
一般来说,最好的做法是在事件中释放异步事件处理程序,这样您就不会遇到像这样的范围/关闭场景:
Public Sub pingHandler(sender As Object, e As System.Net.NetworkInformation.PingCompletedEventArgs)
If sender IsNot Nothing Then
RemoveHandler DirectCast(sender, System.Net.NetworkInformation.Ping).PingCompleted, AddressOf pingHandler
End If
Console.WriteLine("pingCompleted")
End Sub
Public Sub pingDisposed(sender As Object, e As System.EventArgs)
If sender IsNot Nothing Then
RemoveHandler DirectCast(sender, System.Net.NetworkInformation.Ping).Disposed, AddressOf pingDisposed
End If
Console.WriteLine("Disposed")
End Sub