1

我知道这里有人问过类似的问题,但我觉得我没有正确理解。

例如,我有以下代码:

Microsoft.Office.Interop.Outlook.Explorer expl = myOutlooApplication.ActiveExplorer();
if (expl.Selection.Count > 0)
{
    object selObject = expl.Selection[1];
    if (selObject is Microsoft.Office.Interop.Outlook.MailItem)
    {
        mailItem = (selObject as Microsoft.Office.Interop.Outlook.MailItem);
        this.myUserControl.MailItem = mailItem;
    }
}

如您所见,MailItem 被传递给 myUserControl 的一个属性。MyUserControl 稍后将需要访问此属性以从 MailItem 中提取一些信息。

我应该Marshal.ReleaseComObject()在将 MailItem 传递给 myUserControl 以减少 RCW 的引用计数器之后还是这为时过早?

编辑:我的问题是,将从文件系统中打开一个 .msg 文件。关闭检查器后,用户尝试再次打开文件,但它已被锁定,我确信 COM 对象未正确释放是导致该问题的原因。

4

2 回答 2

2

除非您有与 COM 对象相关联的已记录内存泄漏,否则不要开始弄乱MarshalCOM 方法。RCW负责将.NET 的垃圾收集世界转换为 COM 的引用计数世界,并且通常做得很好。

可能会考虑Marshal.FinalReleaseComObject在您确定不会访问对象的托管引用并且COM 对象消耗大量资源的时候强制它退出。您可能需要考虑使用IDisposable包装器将转换为 .NET 术语。在您显示的代码中,您肯定不在那个位置 - 您知道您刚刚将一个托管引用传递给 RCW,myUserControl并且您可能希望它访问该引用。

.NET 对 RCW的引用不是COM 计数的引用类型。

于 2019-02-21T08:52:51.420 回答
2

is运算符创建一个隐式变量,所以你有一个泄漏(GC当然会稍后释放它)。
将您的代码更改为以下内容。它不会帮助您处理 MSG 文件,因为它永远不会通过资源管理器访问。this.myUserControl.MailItem当然也必须在完成后立即释放。

    object selObject = expl.Selection[1];
    MailItem mailItem =  selObject as MailItem;
    if (mailItem != null)
    {
        this.myUserControl.MailItem = mailItem;
    }
    Marshal.ReleaseComObject(mailItem);
于 2019-02-21T16:54:09.243 回答