代码之家  ›  专栏  ›  技术社区  ›  Krzysztof Kozmic

.NET应用程序中COM控件的AccessViolationException

  •  1
  • Krzysztof Kozmic  · 技术社区  · 15 年前

    我正在为一个客户端工作,该客户端有一个VB6应用程序正在迁移到.NET。

    我偶然发现一个错误是,当日志在.NET中异步从数据库中提取一些数据,然后将这些数据转发到COM组件以显示它时,会发生以下错误:

    The Undo operation encountered a context that is different from what was applied in the corresponding Set operation. The possible cause is that a context was Set on the thread and not reverted(undone).
                    Err Source: mscorlib
                    Err Type: System.InvalidOperationException
    
    ERROR stack trace:
       at System.Threading.SynchronizationContextSwitcher.Undo()
       at System.Threading.ExecutionContextSwitcher.Undo()
       at System.Threading.ExecutionContext.runFinallyCode(Object userData, Boolean exceptionThrown)
       at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteBackoutCodeHelper(Object backoutCode, Object userData, Boolean exceptionThrown)
       at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)
       at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
    

    然后日志中会显示以下内容:

    Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
                    Err Source: mscorlib
                    Err Type: System.AccessViolationException
    
    ERROR stack trace:
           at System.RuntimeType.ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData)
           at _Client's component that forwards calls to COM_
    

    有人遇到过这样的事吗?我该如何修复它?

    3 回复  |  直到 15 年前
        1
  •  1
  •   Fredrik Mörk    15 年前

    如果我理解正确的话,这个COM组件是表单中可见的UI组件?如果是这样的话,问题是组件是从另一个线程而不是UI线程更新的吗?您可以尝试以下操作:

    Private Sub MethodThatUpdatesComponent(ByVal data As WhateverType)
        If Me.InvokeRequired Then
            Dim input As Object = { data }    
            Me.Invoke(new Action(Of WhateverType)(AddressOf MethodThatUpdatesComponent), input)
        Else
            ' put the code to update the COM component here '
        End If
    End Sub
    

    这将确保更新组件的代码始终在UI线程上执行。

        3
  •  0
  •   Danielle Paquette-Harvey    15 年前

    我在C++中遇到了同样的问题。(我不是真的做COM,但也许它能帮你。)
    在C++中,当我获得访问冲突时,通常会受到两个问题的影响:
    -您使用的是未初始化的var或空指针
    -缓冲区溢出

    现在我不知道在VB6或COM中是否可以,但是您应该验证每个允许使用新变量的地方,并确保在尝试使用它之前分配了它。
    您还应该检查缓冲区溢出。

    为了帮助您完成这项任务,您可以使用许多可以帮助您的工具。在VB6中,在我的工作中,他们使用“DevPartner”,这是一个很好的工具,可以找到为什么您有访问冲突。
    在visualstudio2005中,“DevPartner”仍然可用,但是微软还提供了一个工具来帮助您查找缓冲区溢出和错误。

    我发现访问冲突是最严重的错误,也是最难找到的错误。它与记忆的使用有关。
    我希望这有帮助!祝你好运!