RCW&安培;在C#中使用COM互操作时,引用计数 [英] RCW & reference counting when using COM interop in C#

查看:453
本文介绍了RCW&安培;在C#中使用COM互操作时,引用计数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用Office互操作程序集的应用程序。我知道有关运行时可调用包装(RCW)由运行时管理。但我不是很确定的引用计数如何被递增。 MSDN说:

I have an application that uses Office interop assemblies. I am aware about the "Runtime Callable Wrapper (RCW)" managed by the runtime. But I am not very sure how the reference count gets incremented. MSDN says,

RCW保留只是一个参考
  包装的COM对象不管
  管理的客户端调用它的数量。

RCW keeps just one reference to the wrapped COM object regardless of the number of managed clients calling it.

如果我理解正确的话,在下面的例子中,

If I understand it correctly, on the following example,

using Microsoft.Office.Interop.Word;

static void Foo(Application wrd)
{
    /* .... */
}

static void Main(string[] args)
{
    var wrd = new Application();
    Foo(wrd);
    /* .... */
}

我传递实例 WRD 来的另一种方法。但是,这不会增加内部引用计数。所以,我想知道在什么情况下引用计数就会增?任何人都可以指出哪里引用计数就会增方案?

I am passing the instance wrd to another method. But this doesn't increment the internal reference count. So I am wondering on what scenarios the reference count gets incremented? Can anyone point out a scenario where the reference count gets incremented?

另外,我看了一些博客与COM对象编程时,它说避免使用双重点。喜欢的东西, wrd.ActiveDocument.ActiveWindow 。提交人声称,编译器创建独立的变量来保存这将增加引用计数器的值。恕我直言,这是错误的,第一个例子证明了这一点。这是否正确?

Also I read some blog which says avoid using double dots when programming with COM objects. Something like, wrd.ActiveDocument.ActiveWindow. The author claims that compiler creates separate variables to hold the values which will increment the reference counter. IMHO, this is wrong and the first example proves this. Is that correct?

任何帮助将是巨大的!

推荐答案

我一直在研究这个问题太,工作的COM / .Net的互操作为中心的应用,战斗泄漏,挂起和崩溃。

I have been researching this question too, working on a COM/.Net-Interop-centric application, fighting leaks, hangs and crashes.

简短的回答:COM对象是从COM环境.NET通过每次

Short answer: Every time the COM object is passed from COM environment to .NET.

龙答:


  1. 对于每个COM对象只有一个RCW对象[测试1] [注释4]

  2. 引用计数的每个对象从COM对象中要求的时间增加(调用返回COM对象的COM对象的属性或方法,返回的COM对象的引用计数将依次递增)[测试1]

  3. 引用计数不被转换为对象的其他COM接口或四处移动RCW参考递增[测试2]

  4. 引用计数的对象是由COM [参考1]
  5. 引发事件中的参数传递,每次递增
  1. For each COM object there is one RCW object [Test 1] [Ref 4]
  2. Reference count is incremented each time the object is requested from within COM object (calling property or method on COM object that return COM object, the returned COM object reference count will be incremented by one) [Test 1]
  3. Reference count is not incremented by casting to other COM interfaces of the object or moving the RCW reference around [Test 2]
  4. Reference count is incremented each time an object is passed as a parameter in event raised by COM [Ref 1]

在一个侧面说明:您应该始终发布COM只要你在使用完对象。离开这个工作交给GC会导致泄漏,意外行为和事件死锁。如果您访问不反对在STA线程上创建它的这是十倍更重要。 [参考文献2] [参考3] [痛苦的个人经历]

On a side note: You should ALWAYS release COM objects as soon as you are finished using them. Leaving this work to the GC can lead to leaks, unexpected behavior and event deadlocks. This is tenfold more important if you access object not on the STA thread it was created on. [Ref 2] [Ref 3] [Painful personal experience]

我希望我已经涵盖了所有的情况,但COM是一个艰难的cookie。
干杯。

I'm hope I have covered all cases, but COM is a tough cookie. Cheers.

测试1 - 引用计数

private void Test1( _Application outlookApp )
{
    var explorer1 = outlookApp.ActiveExplorer();
    var count1 = Marshal.ReleaseComObject(explorer1);
    MessageBox.Show("Count 1:" + count1);

    var explorer2 = outlookApp.ActiveExplorer();
    var explorer3 = outlookApp.ActiveExplorer();
    var explorer4 = outlookApp.ActiveExplorer();

    var equals = explorer2 == explorer3 && ReferenceEquals(explorer2, explorer4);
    var count2 = Marshal.ReleaseComObject(explorer4);
    MessageBox.Show("Count 2:" + count2 + ", Equals: " + equals);
}
Output:
Count 1: 4
Count 2: 6, Equals: True

测试2 - 引用计数续

private static void Test2(_Application outlookApp)
{
    var explorer1 = outlookApp.ActiveExplorer();
    var count1 = Marshal.ReleaseComObject(explorer1);
    MessageBox.Show("Count 1:" + count1);

    var explorer2 = outlookApp.ActiveExplorer();

    var explorer3 = explorer2 as _Explorer;
    var explorer4 = (ExplorerEvents_10_Event)explorer2;
    var explorerObject = (object)explorer2;
    var explorer5 = (Explorer)explorerObject;

    var equals = explorer2 == explorer3 && ReferenceEquals(explorer2, explorer5);
    var count2 = Marshal.ReleaseComObject(explorer4);
    MessageBox.Show("Count 2:" + count2 + ", Equals: " + equals);
}
Output:
Count 1: 4
Count 2: 4, Equals: True

来源我除了我的经验和测试继电器上:

1。约翰内斯路过的 - !RCW引用计数规则= COM引用计数规则

2。伊兰·桑德勒 - 运行时可调用包装内部机制和常见的陷阱

3。伊兰·桑德勒 - Marshal.ReleaseComObject的和CPU纺纱

4。 MSDN - 运行时可调用包装

这篇关于RCW&安培;在C#中使用COM互操作时,引用计数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆