2009-11-21 24 views
1

我正在爲.NET中的遷移過程中具有VB6應用程序的客戶端工作。.NET應用程序中的COM控件中的AccessViolationException

目前他們有一個.NET外殼,但在.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_ 

有沒有人遇到過這樣的事情?我如何解決它?

回答

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線程上執行。

+0

是的,組件是一個UI控件,它很可能是從其他線程更新的。不確定,因爲我還沒有看到代碼,只是得到了日誌。不過,我想我會得到其他異常,如果這確實是其他線程更新UI的問題,還是僅適用於.NET?不知道COM如何處理它。無論如何 - 我會嘗試你的建議。 –

+0

糾正我,如果我錯了,但我相信你可以通過從不同的線程直接更新UI組件來破壞內存。 。 。 –

0

我在C++中遇到了同樣的問題。 (我沒有真正做COM,但也許它可以幫助你。)
在C++中,當我得到訪問衝突時,一般是由兩個問題引起的:
- 您正在使用未初始化的var或NULL指針
- 你有一個緩衝區溢出

現在我不知道是否有可能在VB6或COM,但你應該檢查每一個地方,你讓一個新的變量,並確保你嘗試之前它被分配用它。
您還應該檢查緩衝區溢出。

爲了幫助您完成此任務,您可以使用許多工具來幫助您。在VB6中,在我的工作中,他們使用「DevPartner」,這是一個很好的工具,可以找出訪問衝突的原因。
在Visual Studio 2005中,「DevPartner」仍然可用,但Microsoft也提供了一個工具來幫助您查找緩衝區溢出和錯誤。

我發現訪問衝突是最嚴重的錯誤,也是最難找到的。它與記憶的使用有關。
我希望這有助於!祝你好運!

+0

我曾經做過很多C++,並且只有一件事情比香草Access Violation更糟......當你開始執行隨機存儲器時...... *顫抖*當指令指針變得乾淨時發生。 –

1

這很像是代碼從另一個線程訪問UI的原因。但是,如果您絕對需要從另一個線程訪問COM對象,則可以使用global interface table來編組線程中的COM指針。以下是關於如何使用manipulate COM進行編組的一些提示和技巧。

+0

控件是一個COM控件的事實呢?不是COM做自己的線程管理嗎?這個組件是運行在.NET UI線程還是它自己的?如果它產生了它的線程呢? –

相關問題