2010-01-07 26 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