最近我們使用結構化編程技術重寫了一個工作原型庫以實現可維護性。它使用應用程序的基於COM的API從第三方應用程序(TPA)訪問數據。該API使用Win32消息傳遞(WM_COPYDATA)與TPA進行通信。AccessViolationException在使用COM互操作的.NET應用程序中隨機發生
新的庫代碼:
- 是用C#和Visual Studio 2010 SP1。
- 面向.NET Framework 4(原型中爲3.5)。
- 使用匿名方法和新的自定義泛型類來分解和簡化原始代碼,該代碼不使用(除少數.NET Framework實用程序類型外,如HashSet <>)。
- 使用非嵌入互操作類型(Embed Interop Types = False)和免註冊COM(Isolated = True)引用基於COM的API。
- 將Marshal.ReleaseComObject用於基於COM的API返回的對象的確定性內存管理。
- 僅在單線程單元(基於COM的API爲單元線程)中運行的工作線程上使用基於COM的API。
- 調用基於COM的API時使用早期綁定。
我們的測試應用程序崩潰隨機地基於COM的API中AccessViolationException。堆棧跟蹤顯示這發生在調用UnsafeNativeMethods.DispatchMessageW(請參閱下面的示例)或基於COM的API中的幾個不同屬性中的任何一個。測試人員應用程序是一個帶有菜單,狀態欄和RichTextBox的簡單WinForms應用程序。
此行爲是常見的Windows XP和Windows 7,輔助線程和UI線程之間是否線程間通信已啓用,我們是否通過FinalReleaseComObject更換ReleaseComObject的。當TPA非常繁忙時,它似乎更頻繁地崩潰,例如。而它正在啓動。
原型庫使用VS 2008項目轉換爲VS 2010年後開發,原型應用程序仍然不會崩潰。
System.AccessViolationException未處理消息=嘗試到 讀取或寫入受保護的內存。這通常表示其他 內存已損壞。源= System.Windows.Forms的堆棧跟蹤: 在System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG & MSG) 在System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr的 dwComponentID,的Int32原因,的Int32 pvLoopData) 在System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(的Int32 原因,ApplicationContext的上下文) 在System.Windows.Forms.Application.ThreadContext.RunMessageLoop(的Int32 原因,ApplicationContext的上下文) 在System.Windows.Forms.Application.Run(表格的MainForm) 在IndexerTester.Program.Main()中d:\ TestApps \索引\ IndexerTester \ Program.cs的:線17
你見過類似的問題?
您可以提供有關隔離原因和/或潛在解決方法的任何建議嗎?
調用堆棧顯示正在從工作線程封送到主線程的調用。如果您在該STA線程上創建COM對象,則您的STA才能正常工作。但這不太可能是問題所在,本機代碼很少需要C#程序對AV進行轟炸的幫助。你看不到任何東西,因爲你沒有啓用非託管調試。 –
謝謝,我不知道這個調用堆棧代表了線程間編組。不幸的是,我沒有經歷過非託管調試。我不確定我能否使用它,因爲我無法訪問COM源代碼或其PDB文件。你能建議一些資源來學習如何做到這一點? – groverboy
如果沒有這些資源,你幾乎沒有可能。編寫單元測試來重現崩潰。然後將其發送給代碼所有者,讓他幫助你。 –