使用COM互操作在.NET应用程序中随机发生AccessViolationException

时间:2011-10-27 04:04:12

标签: c# .net com-interop

最近,我们使用结构化编程技术重写了一个工作原型库,以实现可维护性。它使用应用程序的基于COM的API访问来自第三方应用程序(TPA)的数据。 API使用Win32消息传递(WM_COPYDATA)与TPA进行通信。

新的图书馆代码:

  1. 使用Visual Studio 2010 SP1在C#中编写。
  2. 目标.NET Framework 4(原型中为3.5)。
  3. 使用匿名方法和新的自定义泛型类来分解和简化原始代码,原始代码也不使用(除了一些.NET Framework实用程序类型,如HashSet<>)。
  4. 使用未嵌入的互操作类型(嵌入互操作类型= False)和无注册COM(隔离=真)引用基于COM的API。
  5. 使用Marshal.ReleaseComObject进行确定性内存管理,使用基于COM的API返回的对象。
  6. 仅在单线程单元中运行的工作线程上使用基于COM的API(基于COM的API是单元线程的)。
  7. 调用基于COM的API时使用早期绑定。
  8. 我们的测试器应用程序在基于COM的API中随机使用AccessViolationException崩溃。堆栈跟踪显示这发生在对UnsafeNativeMethods.DispatchMessageW(参见下面的示例)或基于COM的API中的任何几个不同属性的调用中。测试器应用程序是一个简单的WinForms应用程序,带有菜单,状态栏和RichTextBox。

    这种行为在Windows XP和Windows 7中很常见,无论是否启用了工作线程和UI线程之间的线程间通信,无论我们是否用FinalReleaseComObject替换ReleaseComObject。当TPA非常繁忙时,它似乎更频繁地崩溃,例如。它正在启动。

    原型库是使用VS 2008开发的。将项目转换为VS 2010后,原型应用程序仍然不会崩溃。

      

    System.AccessViolationException未处理Message = Attempted to   读或写受保护的内存。这通常表明其他   记忆已腐败。 Source = System.Windows.Forms StackTrace:          在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(Form mainForm)          在D:\ TestApps \ Indexer \ IndexerTester \ Program.cs中的IndexerTester.Program.Main():第17行

    你见过类似的问题吗?

    您能否就隔离原因和/或潜在的解决方法提出任何建议?

1 个答案:

答案 0 :(得分:0)

这有点晚,但可以帮助别人。

我们向COM对象的供应商发送了一个错误报告:当使用两个实例时,会发生AccessViolationException,每个实例位于不同的线程上。供应商确认其代码中存在错误(非线程安全的静态变量)并发布修复程序。

我们注意到,当第三方应用程序(TPA)和我们的测试人员应用程序(从TPA读取数据)都忙时,崩溃更频繁。

至关重要的是,我们发现在工作量很大的情况下,使用原型应用程序也会发生崩溃;我们错误地认为我们的重写引入了一个错误。这一发现说服我们向供应商报告此事。