在Outlook中与MailItems交互时使用Marshal.ReleaseComObject
的重要性是什么?
我参考创建C#VSTO Outlook加载项的演练 https://docs.microsoft.com/en-us/visualstudio/vsto/walkthrough-creating-your-first-vsto-add-in-for-outlook?view=vs-2019
其中有修改现有选定邮件项目的主题和正文的示例。
void Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
{
Outlook.MailItem mailItem = Inspector.CurrentItem as Outlook.MailItem;
if (mailItem != null)
{
if (mailItem.EntryID == null)
{
mailItem.Subject = "This text was added by using code";
mailItem.Body = "This text was added by using code";
}
}
}
该示例结束时没有提到使用Marshal.ReleaseComObject
释放邮件项目对象。
但是在https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.releasecomobject?view=netframework-4.8的.Net API参考中,他们提到:
您应该使用此方法来释放底层的COM对象,该对象及时保存对资源的引用,或者在必须按特定顺序释放对象时。
因此,如果我们未能在要引用的MailItem上使用Marshal.ReleaseComObject,那么显然会有一些后果?
是否存在不使用Marshal.ReleaseComObject会导致问题的特定用例?
谢谢
答案 0 :(得分:1)
如果您不调用Marshal.ReleaseComObject
,则该对象将作为垃圾回收器稍后释放的点被释放。通常,这不是问题-在处理大量项目时,您通常需要小心,不要使发行版具有偶然性。在这种特殊情况下,除非使用Marshal.ReleaseComObject
,否则您会很好的,除非您要确保该项目已发布,以防它在外部更新,并且您不希望Outlook对象模型以陈旧的对象结尾。
请注意,Marshal.ReleaseComObject
变量上的mailItem
是不够的-您需要注意隐式变量,例如当您使用多点符号时。某些.Net运算符也以隐式变量结尾,as
是其中之一(以及is
):
void Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
{
object item = Inspector.CurrentItem;
Outlook.MailItem mailItem = item as Outlook.MailItem;
if (mailItem != null)
{
if (mailItem.EntryID == null)
{
mailItem.Subject = "This text was added by using code";
mailItem.Body = "This text was added by using code";
}
Marshal.ReleaseComObject(mailItem);
}
Marshal.ReleaseComObject(item);
}
答案 1 :(得分:0)
TL; DR:不要调用Marshal.ReleaseComObject
,因为它没有用处,更重要的是,它是危险。请参见下面的引文。
在Outlook中与MailItems交互时使用Marshal.ReleaseComObject的重要性是什么?
不需要,您不需要。
如果我们在引用的MailItem上不使用Marshal.ReleaseComObject,那么显然会有一些后果吗?
不正确。
是否存在不使用Marshal.ReleaseComObject会导致问题的特定用例?
不称这是正确的情况。
MSDN article的备注部分有些混乱,并且令人误解。
该行:
您应该使用此方法来释放底层的COM对象,该对象及时保存对资源的引用,或者在必须按特定顺序释放对象时。
...应该真的之后更重要:
因此,
ReleaseComObject
仅在绝对必要时使用。如果要调用此方法以确保在确定的时间释放COM组件,请考虑改用FinalReleaseComObject方法
...并且:
此方法使您可以强制释放RCW参考计数,以便它在您需要的时候准确发生。但是,对ReleaseComObject的不正确使用可能会导致您的应用程序失败,或者可能导致访问冲突
实际上,在正常使用中,您根本不需要调用此方法。
最后,由于您要为Outlook制作外接程序,因此也几乎不需要释放COM对象,因为您访问的任何对象都是由Outlook本身创建的,并且您的代码在与Outlook相同的进程空间中运行。 Outlook已经知道这些对象,并且知道何时摆脱它们。并不是说您正在启动一个外部进程,例如说MS Word,并且在通过COM进行通信后,对Word的孤立实例感到担忧。
Hans Passant说:
不需要自己存储这些对象引用并显式调用Marshal.ReleaseComObject(),CLR会为您完成... more
(尽管提到了Excel,但链接仍然相关,因为Outlook和Excel都使用COM)