使用COM,内存泄漏处理Notes对象

时间:2013-02-14 22:02:18

标签: com memory-leaks lotus-notes lotus-domino lotus

我使用C#与Domino COM进行交互。我正在使用Lotus Notes 8.5.2。 Visual Studio 2008,Windows 7 SP1。

我试图阻止Lotus的这个错误:

LSXBE: ************************************
LSXBE: ****** Out of Backend Memory *******
LSXBE: ************************************

以下代码将NSF中的每个NotesDocument复制到另一个NSF。从具有SELECT @All选择查询的NotesView获取UNID后,代码使用

一次复制一条消息
NotesDocument ndoc = nd.GetDocumentByUNID(nve.UniversalID);         
ndoc.CopyToDatabase(nd2);

鉴于,一个10 GB的源NSF,我的应用程序使用的内存量(我相信的私有字节)稳定增长到大约450 MB。 ANTS Memory Profiler表明几乎所有内存都分配给了非托管内存,即COM。

  1. 我可以通过处理Notes对象来减少内存消耗吗?我还没有看到解除分配NotesSession,NotesDatabase,NotesDocument等的方法。有没有办法解除分配内存?
  2. 我在每5000个文档之后尝试了一个调用GC.Collect()和GC.WaitForPendingFinalizers()的代码版本,它消除了16 GB RAM机器上的“Out of Backend Memory”错误。即使复制完成,我将包含以下代码的对象设置为null并调用垃圾收集,内存利用率仍保持在450 MB左右。

    我还尝试将复制代码放在自己的线程中,然后在线程完成后进行垃圾收集。这没有用。

    1. 如果没有Notes对象的处理方法,我还可以如何降低内存利用率?
    2. 代码C#

      //Establish session
      NotesSession ns = new Domino.NotesSessionClass();
      ns.Initialize("");
      
      //Open source NSF
      NotesDatabase nd = ns.GetDatabase("", "test.nsf", false);
      //Open destination NSF.
      //Assume that all design elements of nd2 are identical to those of nd
      NotesDatabase nd2 = ns.GetDatabase("", "test2.nsf", false);
      
      //Create view that returns all documents.
      NotesView nView2 = nd.GetView("$All");
      nd.CreateView("All-DR", "SELECT @ALL", nView2, false);
      NotesView nView = NotesConnectionDatabase.GetView("All-DR");
      
      //Loop through entries in the new view
      NotesViewEntry nvec = nView.AllEntries;
      nve = nvec.GetFirstEntry();
      
      for (int j = 1; j <= intEntryCount; j++)
      {
           if (j == 1)
           {
                nve = nvec.GetFirstEntry();
           }
           else
           {
                nve = nvec.GetNextEntry(nve);
           }
      
           //Copy document to second database.
           NotesDocument ndoc = nd.GetDocumentByUNID(nve.UniversalID);         
           ndoc.CopyToDatabase(nd2);
       }
       //End loop.
       //All documents are copied.
      

      我有这些想法,其中没有一个是吸引人的:

      1. 每次调用CopyToDatabase后调用垃圾回收。鉴于我相信我正在处理COM中的内存泄漏,我不认为这会起作用。我也希望它能降低我申请的速度。

      2. 尝试使用C ++ API。我不知道那里是否存在问题。

      3. 这是一种非常笨拙的方式...... 构建一个新的经理应用程序 一个。获取列表UNID并将它们写入文本文件。 湾启动复制应用程序。 C。复制应用程序从文本文件中复制记录的子集。 d。复制应用程序终止,释放其内存。 即经理应用程序启动新的复制应用程序进程。 F。根据需要重复c - e。

2 个答案:

答案 0 :(得分:1)

我不相信Domino COM类本身就会泄漏。如果他们这样做,Lotus将像他们在Java类中一样提供recycle()方法。但是在这些类的后面是整个Notes运行时,它确实为缓存分配了大量内存,所以如果你看到内存上升就不足为奇了。

答案 1 :(得分:0)

您是否尝试使用显式命令SetProcessWorkingSetSize()传递参数-1和-1?有时.NET COM对象在显式调用之前不释放内存。 This article更详细地讨论了这一点。

我遇到了类似问题in this SO post,这解决了这个问题。