2013-01-02 238 views
2

我排查線程應用程序的一些奇怪的行爲,並在使用該BeginInvoke(Deligate)調用啓動異步任務數代表的功能都有所涉獵。我的研究表明,在沒有與EndInvoke配對的情況下使用BeginInvoke有機會導致內存泄漏,尤其是在引發異常的情況下,我認爲這種情況就是這種情況。BeginInvoke內存泄漏?

我一直在考慮該代碼調用的委託,並具有調用一個新的委託本身就是一個回調函數。我最感興趣的是回調是如何執行的。是否有必要在最後一行發佈新代表?這個評論似乎對我沒有任何意義。此外,回調的委託調用永遠不會發出導致泄漏的EndInvoke調用,是否有一種更簡單的方法來清理它,然後創建回調方法?

另一個值得關注的,雖然不太重要的是函數的名稱同步。從我看到的方法調用中沒有強制同步。 VB.NET是否會自動設置同步,還是最後一個開發人員只是用語言來表達幻想?

初始呼叫:

mDelegateUpdate3.BeginInvoke(mCallbackUpdate3, mDelegateUpdate3) 

回調方法:

Public Sub OnUpdateSchedule3Complete(ByVal ar As IAsyncResult) 
     ' Clean up original thread 
     Dim del As OPCConnectionWorkerDelegate 
     del = CType(ar.AsyncState, OPCConnectionWorkerDelegate) 
     del.EndInvoke(ar) 

     'We are on the wrong thread so we need to switch back to the UI thread 
     Dim ar1 As IAsyncResult 
     ar1 = Me.BeginInvoke(New SynchronizedScheduleCompletedDelegate(AddressOf Me.SynchronizedScheduleCompleted)) 
End Sub 

的SynchronizedScheduleCompleted方法:

Private Sub SynchronizedScheduleCompleted() 
    mAttemptingUpdate = False 
    mOPCConnectionWorker.clearInvolked() 
    SetInProgress(False) 
End Sub 
+0

你對這個錯誤的軌道。你的代碼實際上調用了EndInvoke()。在最後一行使用的Control.BeginInvoke()調用是一個完全不同的動物,它不**需要EndInvoke()。無論你在泄漏什麼,都不在這個代碼中。使用內存分析器。 –

+0

有趣。我會研究這一點,我不是一個VB程序員,或者.NET,因此我試圖更快地理解這些調用。你有推薦的分析器嗎? – Grambot

回答

2

正確;不調用EndInvoke()會造成內存泄漏。

如果你只是想讓一個異步操作「不再處理」,而不是處理它的結果,你應該簡單地調用ThreadPool.QueueUserWorkItem(),它不存在內存泄漏的可能性。

如果你確實在意結果,你應該使用Task這個類,這是很多更容易使用。

不再有任何理由罵Delegate.BeginInvoke()

而且,字Synchronized在委託和方法的名稱是沒有意義的。

+0

看起來像這樣可以解決代碼的問題,無論是造成更大的未知問題。感謝您的快速回復。 – Grambot