AccessViolationException in COM control in .NET app
I'm working for a client that has a VB6 app in the migration process to .NET.
Currently they have a .NET shell, but host some old VB6 controls in .NET. There's an error I stumbled upon is logs that happens when they in .NET asynchronously pull some data from the database, and then forward that data to a COM component to display it:
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.Invoke开发者_如何学JAVAMarshaledCallback(ThreadMethodEntry tme)
at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
then the following shows up in the logs:
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_
Did anyone ever encounter something like this? How do I approach fixing it?
If I understand it correctly, this COM component is a visible UI component in a form? If so, could it be that the problem is that the component is being updated from another thread than the UI thread? You could try the following:
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
This will ensure that the code that updates the component is always executed on the UI thread.
This is most like cause by code accessing the UI from another thread. However, if you absolutely need to access the COM object from another thread, you can use a global interface table to marshal the COM pointer across the thread. Here are some tips and tricks on how to use a manipulate COM to marshal.
I had the same kind of problems in C++. (I don't really do COM but maybe it can help you.)
In C++, when I get an Access Violation, it is caused by two problems generally:
- You are using an uninitialized var or a NULL pointer
- You have a buffer overflow
Now I don't know if it is possible in VB6 or in COM but you should verify every place where you allow a new variable and make sure that it is allocated before you try to use it.
You should also check for buffer overflow.
To help you in this task, you can use many tools that can help you. In VB6, at my job, they use "DevPartner" wich is a great tool to find why you have Access Violation.
In Visual Studio 2005, "DevPartner" is still available but Microsoft also put in a tool to help you find buffer overflow and errors.
I found that Access Violation are the worst error to have, and the most difficult to find. It is related to memory use.
I hope this helps! Good luck!
精彩评论