处理COM事件时的TargetInvocationException

时间:2010-08-31 16:15:09

标签: .net vb.net events com

我正在开发一个COM dll库,我有一个小的vb.net(vs 2005)应用程序只是为了测试它。

我在应用程序中声明了我的对象

  

Private m_VarName As MyLib.CMyComClass

到目前为止,非常好。

但是现在,我需要一个事件来通知应用程序一些事情,所以我在COM dll中实现了这样的事件,并将声明改为

  

Private WithEvents m_VarName As MyLib.CMyComClass

到目前为止,再次如此好。但是如果我添加一个Sub来处理我的事件:

  

Private Sub m_VarName_OnCaptureStop()处理m_VarName.MyEvent

     

...

     

End Sub

我第一次创建对象时,没有任何不好的事情发生,但如果我重新实现它

  

If(Not m_VarName Is Nothing)Then ReleaseComObject(m_VarName)

     

m_VarName = New MyLib.CMyComClass

然后我得到一个神秘的TargetInvocationException,看似与反射有关(其中,AFAIK,我没有使用)。

如果我删除“Handles m_VarName.MyEvent”部分,一切似乎都有效。如果重要的话,我暂时没有解雇任何事件。 知道为什么会这样的事吗?

1 个答案:

答案 0 :(得分:2)

原因与VB.Net中WithEventsHandles的实现有关。当您在VB.net中声明具有WithEvents修饰符的字段时,它将作为属性生成。

每当通过赋值操作更新该属性时,属性setter将取消订阅旧的事件处理程序,然后在新值上订阅事件处理程序。实际上它看起来像这样

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

如果您在代码的上下文中考虑到实际发生的是以下

ReleaseComObject(m_VarName)
RemoveHandler m_VarName.SomeEvent,m_VarName_OnCaptureStop

所以你在已经发布的COM对象上调用RemoveHandler。因此它会抛出一个Exception

修复很简单,请勿调用ReleaseComObject。实际需要调用此方法的情况非常少,几乎肯定不适用于这种情况。而是让GC正常收集它。