【问题标题】:"COM object that has been separated from its underlying RCW cannot be used" error related to vb.net form event与 vb.net 表单事件相关的“无法使用已与其底层 RCW 分离的 COM 对象”错误
【发布时间】:2017-12-11 17:38:27
【问题描述】:

我将 arcobjects 地图事件连接到 vb.net 表单以监听地图选择更改。这一切正常,但用户在打开表单时偶尔会报告此错误。我看不到任何重现错误的模式,而且它似乎是随机的。

“无法使用已与其底层 RCW 分离的 COM 对象”

它源自我挂钩事件的表单 Load() 方法。

谁能帮我理解我做错了什么?我正在取消 FormClosing() 事件中的地图选择事件,我认为这是正确的方法。

Public Class MyForm

    Private _activeViewEvents As IActiveViewEvents_Event

    Private Sub FormLoad(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        _activeViewEvents = TryCast(pMxDoc.ActiveView.FocusMap, IActiveViewEvents_Event)
        AddHandler _activeViewEvents.SelectionChanged, AddressOf SelectionChanged    
    End Sub

    Private Sub SelectionChanged
        'do something when selection is changed
    End Sub

    Private Sub FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
        RemoveHandler _activeViewEvents.SelectionChanged, AddressOf SelectionChanged
    End Sub

End Class

【问题讨论】:

    标签: vb.net events com arcobjects rcw


    【解决方案1】:

    您创建和销毁处理程序的方法是有效的。当您的表单打开时更改地图文档时,您可能会收到 RCW COM 异常。由于您使用FocusMap 创建句柄,因此当文档发生更改时,FocusMap 也是如此,这意味着您需要为新的地图文档重新创建处理程序。

    【讨论】:

    • 我已经在采用这种方法,但不幸的是问题仍然存在。我的表单也与文档事件挂钩,因此在文档更改时永远不会打开。每当地图文档更改时,用户必须重新加载表单,因此 FormLoad() 总是为新文档重新创建处理程序。我怀疑它与更改地图文档有关,但我会更深入地研究它。
    • 您是否有可能使用MarshalComReleaser 处理资源?
    • 不,我只处理搜索光标,但与此表单或事件无关。
    • 现在通过监听 ActiveViewChanged 事件修复。已发布解决方案。
    【解决方案2】:

    好的,我想我已经通过使用 ActiveViewChanged 事件解决了这个问题。我没有在每个表单加载或新文档事件上重新挂钩事件,而是尝试侦听何时触发 ActiveViewChanged 事件并每次重新挂钩 SelectionChanged 事件。事实证明,每次打开新文档时都会触发多次(不知道为什么)。无论如何,问题似乎已经消失了。下面是一些示例代码:

    Public Class MyForm
    
    Private _activeViewEvents As IActiveViewEvents_Event
    Private _docEvents As IDocumentEvents_Event
    
    Private Sub FormLoad(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        AddHandler _docEvents.ActiveViewChanged, AddressOf ActiveViewChanged
    End Sub
    
    Private Sub ActiveViewChanged()
        Dim maps = pMxDoc.Maps
        For i = 0 to maps.Count - 1 'remove handlers from all maps
            RemoveActiveViewEvents(maps.Item(i))
        Next
        SetupActiveViewEvent(pMxDoc.ActiveView.FocusMap) 'only add handler to active map
    End Sub
    
    Private Sub RemoveActiveViewEvents(map As IMap)
        _activeViewEvents = CType(map, IActiveViewEvents_Event)
        RemoveHandler _activeViewEvents.SelectionChanged, AddressOf SelectionChanged
    End Sub
    
    Private Sub SetupActiveViewEvents(map As IMap)
        _activeViewEvents = CType(map, IActiveViewEvents_Event)
        AddHandler _activeViewEvents.SelectionChanged, AddressOf SelectionChanged
    End Sub
    
    Private Sub SelectionChanged
        'do something when selection is changed
    End Sub
    
    End Class
    

    【讨论】:

      猜你喜欢
      • 2011-11-21
      • 2012-04-27
      • 2011-07-03
      • 1970-01-01
      • 1970-01-01
      • 2022-08-09
      • 1970-01-01
      • 1970-01-01
      • 2012-09-17
      相关资源
      最近更新 更多