Outlook 2007 加载项内存泄漏?

问题描述 投票:0回答:4

我使用 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();
        }            
c# memory-management outlook-addin
4个回答
2
投票

您是否使用

foreach
循环来处理附件(该部分在您的代码片段中被遗漏)?

根据一篇博客文章,

foreach
会导致内存泄漏,而
for
则不会:

OOM.NET:第 2 部分 - Outlook 项目泄漏

显然还有一个 Hotfix 可以修复有关内存泄漏的各种问题。

更新

您是否尝试过释放附件集合中包含的每个附件?

for (int i = 1; i <= oAttachs.Count; i++)
{
    Outlook.Attachment oAttach = oAttachs[i];

    // Do nothing with attachment
    Marshal.ReleaseCOMObject(oAttach);
    oAttach = null;
}

0
投票

如果没有别的事,我会在调用此行之前先检查 Msg 对象是否有附件:

 Outlook.Attachments objAttachments = Msg.Attachments;

否则,无论是否存在附件,您都会为每条消息分配...因此,如果只有 5,000 条带有附件的消息,则应该只执行 5,000 次,而不是全部约 25,000 次


0
投票

您是否尝试检查 Marshal.ReleaseComObject() 是否始终返回 0 也许您在某处有其他引用?

此外,您是否发现任何废弃物品。那么你应该调用Dispose()


0
投票

我似乎已经解决了这个问题。由于 objSelectedItems 是通过 Applicaiton.ActiveExplorer().Selection 引入的,所以我执行了以下操作:

  1. 将 objSelectedItems 中的每个对象复制到本地声明的 List 中。
  2. 调用 Marshal.ReleaseComObject(objSelectedItems)。
  3. 开始我的循环,如上面问题中发布的那样 - 尽管修改为使用本地对象列表而不是 Outlook 选择。

这显然意味着,出于某种原因,必须先释放选择,然后才能释放其中的各个对象。

© www.soinside.com 2019 - 2024. All rights reserved.