我正在对线程应用程序的一些奇怪行为进行故障排除,并偶然发现了一些使用BeginInvoke(Deligate)
调用来启动异步任务的委托函数。我的研究表明,使用BeginInvoke
而不与EndInvoke
配对有机会导致内存泄漏,特别是在抛出异常的情况下,我认为这就是这种情况。
我给出的代码调用了一个委托,并且有一个回调函数,可以调用一个新的委托。我最好奇的是如何执行回调。是否有必要在最后一行发布新的委托?这个评论似乎对我没有任何意义。此外,回调的委托调用永远不会发出导致泄漏的EndInvoke
调用,是否有更简单的方法来清除它然后创建回调方法?
另一个问题虽然不那么重要,但该函数的名称为Synchronized。从我看到的方法调用没有任何强制同步。 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 :(得分:2)
正确;不调用EndInvoke()
会造成内存泄漏。
如果您只想“发射并忘记”异步操作而不处理其结果,则只需调用ThreadPool.QueueUserWorkItem()
,它不会发生内存泄漏。
如果你关心结果,你应该使用 更容易使用的Task
类。
没有任何理由致电Delegate.BeginInvoke()
。
而且,委托名称和方法中的单词Synchronized
毫无意义。