2010-01-07 4 views
3

Hey, j'essaie d'utiliser la bibliothèque Microsoft.MSHTML (Version 7.0.3300.0) pour extraire le texte du corps à partir d'une chaîne HTML. J'ai extrait cette fonctionnalité dans une seule méthode d'assistance GetBody (string).Utilisation de Microsoft.MSHTML dans une boucle, fuite de mémoire

Lorsqu'il est appelé dans une boucle infinie, le processus manque finalement de mémoire (confirmé par l'utilisation de Mem dans Task Manager). Je suspecte que le problème est dû à mon nettoyage incorrect des objets MSHTML. Qu'est-ce que je fais mal?

Ma définition actuelle de GetBody (string) est:

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; 
} 

Edit: la fuite de mémoire a été tracée au code utilisé dans peuplant une valeur pour html. Dans ce cas, c'était Outlook Redemption.

+0

MSHTML peut lui-même avoir une fuite interne. Exactement combien de temps avez-vous laissé courir cette "boucle infinie"? – EricLaw

+0

La boucle fonctionne pour ~ 500k appels. À ce stade, l'utilisation de la mémoire a atteint 1.6gb et System.OutOfMemoryExceptions commence à être lancé. – NoizWaves

Répondre

2

Cela fait longtemps que j'ai utilisé mshtml, mais l'interface IHTMLElement2 n'a-t-elle pas une méthode close? Avez-vous essayé de l'appeler?

Combien de temps la boucle a-t-elle fonctionné avant que la fuite ne soit évidente?

Je vais voir si je peux trouver un peu du code hérité que j'ai ici qui utilise mshtml et voir comment les développeurs ont libéré les objets.

EDIT:

Le vieux code que nous avons ici appelle près de la HTMLDocument2 puis relâchez l'objet com comme vous l'avez. Cependant, une chose à noter est que la méthode ReleaseComObject est appelée dans une boucle jusqu'à ce qu'elle retourne zéro. Cela assurera que tous les wrapers et l'objet original sont libérés, il y a une note à ce sujet here.

+0

Merci! Je peux voir une méthode close() sur IHTMLDocument2, je vais ajouter un appel et voir comment ça se passe. La fuite elle-même est assez cohérente, l'utilisation de la mémoire ne cesse de croître une fois que le programme commence à s'exécuter. – NoizWaves

+0

Je pense que c'est le cas. Puisque IHTMLDocument2 est un objet COM, il n'est probablement pas géré explicitement par la garbage collection .NET. Puisque, dans votre boucle, vous créez une nouvelle instance d'un objet qui implémente cette interface sans nettoyer l'instance précédente, vous obtiendrez une fuite de mémoire. –

+0

@Caelum - l'appel à close() a légèrement ralenti la fuite, mais il est toujours présent. @Matt - C'est ce que je pense aussi, savez-vous comment je devrais nettoyer les instances précédentes? – NoizWaves