2013-01-07 25 views
2

對於異步對象使用Using塊是否安全?如果該塊在異步任務完成之前退出,該對象是否會過早處理?任務完成後是否會妥善處置?你應該使用「使用」的異步對象?

此代碼有效,但我不知道它是否濫用我的記憶。

For i = 1 To nPings 
    Thread.Sleep(10) 
    Using pPing As New System.Net.NetworkInformation.Ping 
    AddHandler pPing.PingCompleted, AddressOf pingHandler 
    pPing.SendAsync(ip, timeout) 
    End Using 
Next i 

回答

3

如果塊在異步任務完成之前退出,對象是否會過早處理?

是的。一旦End Using行完成,Ping對象將被處置。

任務完成後是否正確處置?

在您的例子中,Ping對象將總是被設置的。但是,在異步代碼完成後,這可能會發生,也可能不會發生,因爲您的代碼編寫方式未確定。

爲了使這種行爲更具有確定性,平安對象的處置您的pingHandler代碼中,使得:

Class PingAsyncState 

    Public Property Ping Ping 
    Public Property int Timeout 

End Class 

For i = 1 To nPings 
    Thread.Sleep(10) 
    pPing As New System.Net.NetworkInformation.Ping 
    AddHandler pPing.PingCompleted, AddressOf pingHandler 
    pPing.SendAsync(ip, new PingAsyncState() With { .Ping = pPing, .Timeout = timeout }) 
Next i 

Sub PingHandler(obj As Object) 

    Dim state = CType(state, PingAsyncState)  

    ... code to do stuff ... 

    state.Ping.Dispose() 

End Sub 

另外,如果你檢查Ping.Dispose()裏面的代碼,你會發現它關閉各種EventHandles。如果Ping對象在異步完成之前被放置,這可能不會導致異常,但它肯定會使Ping對象處於不穩定狀態。您可能會發現事件沒有被觸發,或者異步完成處理程序代碼沒有被調用或者其他微妙的事情發生。

+0

Competent_tech幾乎是正確的,對象即使在處置後也會生存。只是這不會在100%的時間內發生。正如Thilak Nathen所說,結果是不確定的。 在End End後面使用ping對象,直到Sub退出,然後有時最後一個事件不會觸發。我結束了使用後臺工作者和同步ping。 – xpda

2

我肯定還有其他的,可以給你.NET Framework的基礎行爲的詳細解釋,但結果是,通過將事件處理程序,對象將活到觸發事件是即使處置。

您可以通過以下修改證明了這一點:

' 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 

在這種情況下,處置事件可以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 
相關問題