2

我正在对线程应用程序的一些奇怪行为进行故障排除,并且偶然发现了一些使用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
4

1 回答 1

2

正确的; 不调用EndInvoke()会造成内存泄漏。

如果您只想“触发并忘记”一个异步操作而不处理其结果,您应该简单地调用ThreadPool.QueueUserWorkItem(),这不会导致内存泄漏。

如果您确实关心结果,则应该使用容易使用的Task类。

再也没有理由打电话了Delegate.BeginInvoke()

而且,委托和方法名称中的单词Synchronized是没有意义的。

于 2013-01-02T15:57:18.233 回答