在C#中释放COM对象

我知道这已经讨论过了,但我找不到满意的答案。

我有一个电子邮件文件(.msg),我打开如下,然后调用显示。

oApp = new Microsoft.Office.Interop.Outlook.Application(); mail = (Microsoft.Office.Interop.Outlook.MailItem)oApp.Session.OpenSharedItem(fileName); mail.Display(false); oApp = null; // do I need to release this object ? 

用户可以关闭它并重新打开它。 在他们点击“重新打开”之前,我检查窗口是否仍然存在,如果是,那么只需将SetForeground(hwnd)发送到该窗口。 如果不是,那意味着用户关闭了它,所以只需释放mailItem对象并再次打开。

  public static void ReleaseCOMObject(Microsoft.Office.Interop.Outlook.MailItem item) { int r = System.Runtime.InteropServices.Marshal.ReleaseComObject(item); while (r != 0) { r = System.Runtime.InteropServices.Marshal.ReleaseComObject(item); } } 

如果我再次尝试打开同一个文件。 它“有时”会抛出“正在使用的文件exception”所以,我认为即使我发布了MailItem,它也没有被正确发布。

我该怎么做才能确保其正确发布。 关闭和重新打开文件是一种非常常见的情况。

任何指针都会非常有用。

如果您正在使用.NET的COM-interopfunction(您是),那么您不必担心这一点。

COM跟踪引用计数 – 当引用计数达到0时COM对象自动释放 – 并且.NET负责为您使用标准COM引用计数机制。

如果你是P / Invoking到C库,事情可能会有所不同 – 但你不应该像你的标准场景一样担心。

做这样的事情:

 mail = (Microsoft.Office.Interop.Outlook.MailItem)oApp.Session.OpenSharedItem(fileName); 

即使您调用ReleaseComObject也会导致引用不被处理,因为对子对象的引用尚未正确处理。

你应该像这样打电话:

 session = oApp.Session; mail = (Microsoft.Office.Interop.Outlook.MailItem)session.OpenSharedItem(fileName); 

你应该依次处理每个子对象,比如session。