2010-01-07 80 views
3

嘿,我试图使用Microsoft.MSHTML(版本7.0.3300.0)库从HTML字符串中提取正文文本。我已经将这个功能抽象成一个帮助方法GetBody(string)。在循环中使用Microsoft.MSHTML,内存泄漏

当在无限循环中调用时,该进程最终将耗尽内存(通过观察任务管理器中的内存使用情况进行确认)。我怀疑这个问题是由于我对MSHTML对象的错误清理。我究竟做错了什么?

我当前GetBody(串)的定义是:

public static string GetBody(string html) 
{ 
    mshtml.IHTMLDocument2 htmlDoc = null; 
    mshtml.IHTMLElement bodyElement = null; 
    string body; 

    try 
    { 
     htmlDoc = new mshtml.HTMLDocumentClass(); 
     htmlDoc.write(html); 
     bodyElement = htmlDoc.body; 
     body = bodyElement.innerText; 
    } 
    catch (Exception ex) 
    { 
     Trace.TraceError("Failed to use MSHTML to parse HTML body: " + ex.Message); 
     body = email.Body; 
    } 
    finally 
    { 
     if (bodyElement != null) 
      Marshal.ReleaseComObject(bodyElement); 
     if (htmlDoc != null) 
      Marshal.ReleaseComObject(htmlDoc); 
    } 

    return body; 
} 

编辑:内存泄漏已被追踪到在填充HTML的值使用的代码。在这种情况下,它是Outlook Redemption。

+0

MSHTML本身可能在内部泄漏。你究竟让这个“无限循环”运行多久? – EricLaw 2010-01-07 03:07:50

+0

循环运行约500k次呼叫。在那个阶段,内存使用量达到了1.6GB,并且System.OutOfMemoryExceptions开始被抛出。 – NoizWaves 2010-01-07 05:19:32

回答

2

从我使用mshtml开始已经很长时间了,但是IHTMLElement2接口没有使用close方法吗?你有没有试过调用它?

在泄漏明显之前循环运行了多久?

我会看看是否可以挖掘一些我在这里使用mshtml的遗留代码,看看开发人员如何发布这些对象。

编辑:

旧的代码,我们在这里呼吁关闭HTMLDocument2然后释放COM对象上你拥有了它。

但有一点需要注意的是,ReleaseComObject方法在循环中调用,直到它返回零。这将确保所有的com包装和原始对象都被释放,有关于它的注释here

+0

谢谢!我可以在IHTMLDocument2上看到一个close()方法,我将添加一个对它的调用,看看它是如何发生的。泄漏本身非常一致,一旦程序开始执行,内存使用率就会稳步增长。 – NoizWaves 2010-01-07 05:27:58

+0

我会怀疑是这样的。由于IHTMLDocument2是一个COM对象,它很可能不会被.NET垃圾回收显式处理。因为在你的循环中,你创建了一个实现这个接口的对象的新实例,而不清除以前的实例,你会得到一个内存泄漏。 – 2010-01-07 19:31:12

+0

@Caelum - 关闭()的调用稍微减缓了泄漏的速度,但它仍然存在。 @Matt - 这也是我的想法,你知道我应该如何清理以前的实例吗? – NoizWaves 2010-01-07 22:53:09