我使用 C# 创建了一个简单的 Outlook 2007 加载项,它循环选择消息并检查其附件。
我正在一组约 25,000 条选定的消息上运行此加载项。然而,我立即注意到 Outlook 的内存使用量(通过 perfmon 查看)猛增。在调试模式下逐行运行该加载项后,很明显,在第一次访问消息的附件集合时,内存就分配给了 Outlook。该内存永远不会返回到系统; Outlook 继续消耗内存,直到达到约 1GB(大约 12,000 封邮件后),随后我收到“内存或系统资源不足”错误。有什么想法吗?
这是部分代码:
for(int i = 1; i <= objSelectedItems.Count; i++)
{
Object objMsg = objSelectedItems[i];
//Only process if Item is a Message
if (objMsg is Outlook.MailItem)
{
Outlook.MailItem Msg = objMsg as Outlook.MailItem;
//The culprit: this allocates memory to Outlook which I can't get back
Outlook.Attachments objAttachments = Msg.Attachments;
//Perform some actual work here//
//Clean up Outlook objects; does not appear to give memory back to system
Msg.Close(Microsoft.Office.Interop.Outlook.OlInspectorClose.olDiscard);
Marshal.ReleaseComObject(objAttachments);
Marshal.ReleaseComObject(Msg);
}
Marshal.ReleaseComObject(objMsg);
GC.Collect();
GC.WaitForPendingFinalizers();
}
您是否使用
foreach
循环来处理附件(该部分在您的代码片段中被遗漏)?
根据一篇博客文章,
foreach
会导致内存泄漏,而for
则不会:
显然还有一个 Hotfix 可以修复有关内存泄漏的各种问题。
更新
您是否尝试过释放附件集合中包含的每个附件?
for (int i = 1; i <= oAttachs.Count; i++)
{
Outlook.Attachment oAttach = oAttachs[i];
// Do nothing with attachment
Marshal.ReleaseCOMObject(oAttach);
oAttach = null;
}
如果没有别的事,我会在调用此行之前先检查 Msg 对象是否有附件:
Outlook.Attachments objAttachments = Msg.Attachments;
否则,无论是否存在附件,您都会为每条消息分配...因此,如果只有 5,000 条带有附件的消息,则应该只执行 5,000 次,而不是全部约 25,000 次
您是否尝试检查 Marshal.ReleaseComObject() 是否始终返回 0 也许您在某处有其他引用?
此外,您是否发现任何废弃物品。那么你应该调用Dispose()
我似乎已经解决了这个问题。由于 objSelectedItems 是通过 Applicaiton.ActiveExplorer().Selection 引入的,所以我执行了以下操作:
这显然意味着,出于某种原因,必须先释放选择,然后才能释放其中的各个对象。