gpt4 book ai didi

interop - 无法使用已与其底层 RCW 分离的 COM 对象

转载 作者:行者123 更新时间:2023-12-02 08:34:26 27 4
gpt4 key购买 nike

我正在尝试使用 OpcRcw.da.dll。如果我在测试控制台项目中互操作这个 dll,一切正常,但是如果我构建 dll 项目来进行互操作体操并将我的库引用到我的控制台项目中,我会收到此错误:

COM object that has been separated from its underlying RCW cannot be used.

需要对类库项目做什么才能不杀死 RCW 引用?

最佳答案

发生这种情况的原因有多种,我所知道的主要原因如下。

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

调用者订阅 com 对象上的事件,而不保留对回调委托(delegate)的强引用。以下是如何正确执行此操作以及如何不执行此操作的示例:这样做的原因是委托(delegate)需要保留强引用,如果它超出范围,包装器将释放接口(interface)的引用计数,并且会发生不好的事情。

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()
  • 您的表单 virtual Dispose() 将被调用,希望在某个地方调用 base.Dispose() 。 Systems.Windows.Forms.Dispose() 将释放表单上的所有 COM 对象和事件同步,甚至从子控件中释放。
  • 如果拥有 com 对象的控件在 base.Dispose() 之后显式释放,并且如果它调用其 COM 对象上的任何方法,这些方法现在将失败,并且您将收到错误“COM 对象已与其分离”无法使用底层 RCW”。

调试步骤

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

  1. 编写一个继承自 Interop 类的类(也称为运行时可调用包装器或 RCW)。
  2. 重写DetachEventSink
  3. 覆盖处理
  4. 调用您的新类,而不是直接调用互操作类
  5. 向 DetachEventSink 和 Dispose 添加断点
  6. 查看是谁无序调用这些方法

还有一件事

这与此问题无关,但当我们讨论该主题时,除非您知道其他情况,否则请始终记住检查正在使用 COM 对象的线程是否标记为 STA。您可以通过中断调试器并检查从以下位置返回的值来完成此操作:

Thread.CurrentThread.GetApartmentState();

关于interop - 无法使用已与其底层 RCW 分离的 COM 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1567017/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com