2009-10-15 78 views
3

我已经使用C#创建了一个简单的Outlook 2007加载项,它通过选择消息循环并检查其附件。Outlook 2007加载项内存泄漏?

我在一组〜25,000选定的消息上运行此加载项。不过,我立即注意到Outlook的内存使用情况(通过perfmon看到)正在上升。在逐行调试模式下运行加载项后,显然在访问Message's Attachments集合的第一个实例时将内存分配给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(); 
     }    
+0

该修复程序是否解决了您的问题?也许你需要释放每一个附件(见我的更新)? – 2009-10-15 22:00:49

回答

0

我似乎已经解决了这个问题。由于objSelectedItems经Applicaiton.ActiveExplorer()的选择带来了,我做了以下内容:

  1. 复制每个对象objSelectedItems成局部声明的列表。
  2. 调用Marshal.ReleaseComObject(objSelectedItems)。
  3. 开始我的循环发布上述问题 - 虽然修改为使用本地对象列表,而不是Outlook选择。

这显然意味着,出于某种原因,选择必须在其中的各个对象被释放之前被释放。

0

如果不出意外我会先调用此行之前检查附件的消息对象:

Outlook.Attachments objAttachments = Msg.Attachments; 

否则你分配为每每封邮件,无论附件是否存在......所以如果只有5000条带附件的邮件,应该只做5000次而不是全部〜25,000次

+0

这样的条件,如'if(Msg.Attachments.Count> 0){}',也会导致分配相同数量的内存。 – NickL 2009-10-15 17:02:41

2

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

根据博客文章foreach导致内存泄漏而for并不:

OOM.NET: Part 2 - Outlook Item Leaks

显然还存在有关内存泄漏Hotfix提供固定的各种问题。

UPDATE

你试过释放包含在附件集合中的每个单独的附件?

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

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

今天早上我使用了一个foreach,但是我今天早些时候偶然发现了这个OOM.NET文章,并将我的代码更改为上面看到的for循环,但没有任何效果。我只是开始寻找你发布的修补程序... – NickL 2009-10-15 17:10:51

+0

因此,与foreach不是原因。无论如何,OOM似乎有点棘手。您是否尝试在发布代码时运行代码(即,没有“//执行您在此处的某些实际工作”部分)?这仍然有内存泄漏?否则,问题可能在代码的特定部分(无论如何,我会尝试评论代码的某些部分,直到内存泄漏消失;调试器可能不会在代码中显示正确的位置)。 – 2009-10-15 17:40:59

+0

是的,我发布的代码实际上就是我正在运行的代码。我已经实施了“实际工作”代码,但暂时被注释掉了。罪魁祸首绝对是我第一次访问Msg.Attachments的那一行(不管是我的示例中的新对象的分配,还是一个简单的检查条件,比如Msg.Attachments.Count)。没有这条线,我没有问题(但是,当然,也无法访问附件)。 – NickL 2009-10-15 17:48:44

0

你是否试图检查Marshal.ReleaseComObject()总是返回0也许你有其他的引用?

此外,您是否找到任何Dispose项目。那么你应该打电话给Dispose()

+0

我刚刚调查了这个建议 - 我对Marshal.ReleaseComObject()的调用总是返回为<= 0,我认为这是OK。 – NickL 2009-10-15 17:03:43