TargetInvocationException when handling a COM Event
I am developing a COM dll library, and I have a little vb.net (vs 2005) application just to test it.
I had my object declared in the application as
Private m_VarName As MyLib.CMyComClass
So far, so good.
But now, I need an event to inform the application of some things, so I implemented such event in the COM dll, and changed the declaration to
Private WithEvents m_VarName As MyLib.CMyComClass
So far, so good, again. But if I add a Sub to handle my event:
Private Sub m_VarName_OnCaptureStop() Handles m_VarName.MyEvent
...
End Sub
The first time I create the object, nothing bad happens, but if I reinstantiate it
If (Not m_VarName Is Nothing) Then ReleaseComObject(m_VarName)
m_VarName= New MyLib.CMyComClass
then I get a cryptic TargetInvocationException, seemingly related to reflection (which, AFAIK, I am not using).
If I remove the "Handles m_VarName.MyEvent" part, everything seems to work. In c开发者_开发问答ase it matters, I am not firing any event, for now. Any idea about why this happens?
The reason why has to do with the implementation of WithEvents
and Handles
in VB.Net. When you declare a field with the WithEvents
modifier in VB.net it will be generated as a property.
Whenever that property is updated via an assignment operation the property setter will unsubscribe from the old event handler and then subscribe to the event handler on the new value. In effect it looks like this
Property m_VarName as SomeType
Set
if _m_VarName isNot Nothing Then
RemoveHandler _m_VarName.SomeEVent,m_VarName_OnCaptureStop
End If
_m_VarName = Value
AddHandler _m_VarName.SomeEvent,m_VarName_OnCaptureStop
End Set
End Property
If you consider that in the context of your code what's essentially happening is the following
ReleaseComObject(m_VarName)
RemoveHandler m_VarName.SomeEvent,m_VarName_OnCaptureStop
So you're calling RemoveHandler
on a COM object which is already released. Hence it throws an Exception
.
The fix is simple, don't call ReleaseComObject
. The number of situations where you actually need to call this method are very small and almost certainly not applicable to this situation. Instead just let the GC collect it normally.
精彩评论