我正在为一个在.NET迁移过程中拥有VB6应用程序的客户端工作。
目前他们有一个.NET shell,但在.NET中托管一些旧的VB6控件。 我偶然发现了一个错误,当他们在.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_
有没有人遇到过这样的事情?我该如何解决它?
答案 0 :(得分:1)
如果我理解正确,这个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线程上执行。
答案 1 :(得分:1)
这最常见的原因是代码从另一个线程访问UI。但是,如果您绝对需要从另一个线程访问COM对象,则可以使用global interface table来编组线程中的COM指针。以下是有关如何使用manipulate COM编组的一些提示和技巧。
答案 2 :(得分:0)
我在C ++中遇到了同样的问题。 (我不是真的做COM但也许它可以帮助你。)
在C ++中,当我遇到访问冲突时,通常是由两个问题引起的:
- 您正在使用未初始化的var或NULL指针
- 你有一个缓冲区溢出
现在我不知道在VB6或COM中是否可以,但是你应该验证允许新变量的每个地方,并确保在你尝试使用它之前分配它。
您还应该检查缓冲区溢出
为了帮助您完成此任务,您可以使用许多可以帮助您的工具。在VB6中,在我的工作中,他们使用“DevPartner”,这是一个很好的工具,可以找到访问冲突的原因。
在Visual Studio 2005中,“DevPartner”仍然可用,但Microsoft还提供了一个工具来帮助您查找缓冲区溢出和错误。
我发现访问冲突是最糟糕的错误,也是最难找到的错误。它与内存使用有关。
我希望这有帮助!祝你好运!