Nav*_*K N 20 c# com ms-office rcw office-pia
我有一个使用Office互操作程序集的应用程序.我知道运行时管理的"运行时可调用包装器(RCW)".但我不太确定引用计数如何增加.MSDN说,
RCW只保留对包装的COM对象的一个引用,而不管调用它的受管客户端的数量.
如果我理解正确,在以下示例中,
using Microsoft.Office.Interop.Word;
static void Foo(Application wrd)
{
/* .... */
}
static void Main(string[] args)
{
var wrd = new Application();
Foo(wrd);
/* .... */
}
Run Code Online (Sandbox Code Playgroud)
我将实例传递wrd给另一个方法.但这不会增加内部引用计数.所以我想知道引用计数增加的场景是什么?任何人都可以指出引用计数增加的情况吗?
另外我读了一些博客,说在使用COM对象编程时避免使用双点.像,wrd.ActiveDocument.ActiveWindow.作者声称编译器创建单独的变量来保存将增加引用计数器的值.恕我直言,这是错误的,第一个例子证明了这一点.那是对的吗?
任何帮助都会很棒!
Art*_*hur 45
我一直在研究这个问题,研究COM/.Net-Interop为中心的应用程序,防止泄漏,挂起和崩溃.
简短回答:每次COM对象从COM环境传递到.NET.
答案很长:
在一个侧面说明:您应该始终只要您使用完释放COM对象.将此工作留给GC可能会导致泄漏,意外行为和事件死锁.如果您访问的对象不是在创建的STA线程上,那么这十分重要.[参考2] [参考3] [痛苦的个人经历]
我希望我已涵盖所有案例,但COM是一个艰难的cookie.干杯.
测试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
Run Code Online (Sandbox Code Playgroud)
测试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
Run Code Online (Sandbox Code Playgroud)
除了我的经验和测试之外,我继续传播的来源:
1. Johannes Passing的 - RCW参考计数规则!= COM参考计数规则
2. Eran Sandler - Runtime Callable Wrapper Internals和常见的陷阱
3. Eran Sandler - Marshal.ReleaseComObject和CPU Spinning