基になる .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 の検索や応答の受信に時間がかかりすぎると、pingHandler イベントが発生する前に dispose イベントが発生する可能性がありますが、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