已经从其基础RCW分离的COM对象不能使用

我正在尝试使用OpcRcw.da.dll。 如果我互操作这个DLL在一个testing控制台项目内一切正常,但如果我build立的DLL项目做我的interop体操和ref我的图书馆到我的控制台项目我得到这个错误:

已经从其基础RCW分离的COM对象不能使用。

什么需要做一个类库项目不杀死RCW ref?

这很难说出你的实际应用程序在做什么,但是听起来好像你可能正在实例化COM对象,然后尝试从另一个线程访问它,也许在Timer.Elapsed事件中。 如果您的应用程序是multithreading的,则需要在将要使用它的每个线程中实例化COM对象。

这可能发生的原因有几个,我知道的大的是在下面。

没有对委托的强引用的事件处理程序

调用者订阅com对象上的事件,而不保留对callback委托的强引用。 这里是一个如何正确地做到这一点的示例,以及如何做到这一点:其原因是一个强大的引用需要保持到委托,如果超出范围,包装将释放接口的引用计数不好的事情会发生。

public class SomeClass { private Interop.ComObjectWrapper comObject; private event ComEventHandler comEventHandler; public SomeClass() { comObject = new Interop.ComObjectWrapper(); // NO - BAD! comObject.SomeEvent += new ComEventHandler(EventCallback); // YES - GOOD! comEventHandler = new ComEventHandler(EventCallback); comObject.SomeEvent += comEventHandler } public void EventCallback() { // DO WORK } } 

调用处置的运行时可调用包装器

包装已经处理完毕,打完电话后, 如果一个控件使用ActiveX控件或COM对象,而控件Dispose()被乱序调用,则可能发生的常见方法是。

  • 一个表单被调用Close()。
  • System.Windows.Forms.Close()将调用Dispose()
  • 你的窗体虚拟Dispose()将被调用,希望调用base.Dispose()的地方。 Systems.Windows.Forms.Dispose()将释放窗体上的所有COM对象和事件同步,即使是从子控件。
  • 如果拥有一个com对象的控件在base.Dispose()之后被显式地处理,并且它调用了它的COM对象上的任何方法,则这些方法现在将失败,并且将会出现错误:“与其基础RCW分离的COM对象不能使用”。

debugging步骤

debugging此问题的一个好方法是执行以下操作:

  1. 编写从Interop类inheritance的类(也称为运行时可调用包装器或RCW)。
  2. 覆盖DetachEventSink
  3. 覆盖处置
  4. 调用你的新类,而不是直接调用interop类
  5. 将断点添加到DetachEventSink和Dispose
  6. 查看谁在乱序调用这些方法

还有一件事

这与这个问题没有关系,但是当我们谈论这个话题的时候,除非你知道,否则记得检查你的COM对象被使用的线程是否被标记为STA。 您可以通过打破debugging器并检查从以下位置返回的值来做到这一点:

 Thread.CurrentThread.GetApartmentState();