Ich verwende MSHTML mit einem WebBrowser-Steuerelement, weil es mir Zugriff auf Dinge gibt, die der WebBrowser nicht tut, wie Textknoten. Ich habe mehrere Posts hier und im Internet gesehen, wo Leute sagen, dass Sie ReleaseComObject
für jedes COM-Objekt aufrufen müssen, auf das Sie verweisen. Also, sage ich dies tun:Muss ich ReleaseComObject für jedes MSHTML-Objekt unbedingt aufrufen?
var doc = myBrowser.Document.DomDocument as IHTMLDocument2;
Muss ich doc
veröffentlichen? Wie body
in diesem Code:
var body = (myBrowser.Document.DomDocument as IHTMLDocument2).body;
Sind nicht diese Aufgaben durch ein RCW gewickelt, dass sie so bald freigeben würde, da es keine weiteren Artikeln zu ihnen? Wenn nicht, wäre es eine gute Idee, einen Wrapper für jeden von ihnen mit einem Finalizer zu erstellen (anstatt Dispose zu verwenden), der sie freigibt, sobald der Garbage Collector startet (so dass ich mir keine Gedanken machen muss) entsorgt sie)?
Die Sache ist, meine Anwendung hat ein Speicherleck und ich glaube, dass damit verbunden ist. Laut ANTS-Speicherprofiler ist eine der Funktionen (neben vielen anderen, die MSHTML-Objekte verwenden), die einen Verweis auf eine Reihe von Microsoft.CSharp.RuntimeBinder.Semantics.LocalVariableSymbol
Objekten enthält, die sich in der obersten Liste von Objekten befinden, die Speicher in Generation 2 verwenden:
Nicht sicher, was hier falsch ist, da attribute
nur eine Zeichenfolge ist.
Hier ist eine weitere Funktion, die Instanz Retention des Diagramms auf der ANTS Profiler angezeigt wird (Ich habe eine Reihe von FinalReleaseComObject
s ist aber nach wie vor angezeigt):
private void InjectFunction(IHTMLDocument2 document)
{
if (null == Document) throw new Exception("Cannot access current document's HTML or document is not an HTML.");
try
{
IHTMLDocument3 doc3 = document as IHTMLDocument3;
IHTMLElementCollection collection = doc3.getElementsByTagName("head");
IHTMLDOMNode head = collection.item(0);
IHTMLElement scriptElement = document.createElement("script");
IHTMLScriptElement script = (IHTMLScriptElement)scriptElement;
IHTMLDOMNode scriptNode = (IHTMLDOMNode)scriptElement;
script.text = CurrentFuncs;
head.AppendChild(scriptNode);
if (Document.InvokeScript(CurrentTestFuncName) == null) throw new Exception("Cannot inject Javascript code right now.");
Marshal.FinalReleaseComObject(scriptNode);
Marshal.FinalReleaseComObject(script);
Marshal.FinalReleaseComObject(scriptElement);
Marshal.FinalReleaseComObject(head);
Marshal.FinalReleaseComObject(collection);
//Marshal.FinalReleaseComObject(doc3);
}
catch (Exception ex)
{
throw ex;
}
}
ich hinzugefügt, die ReleaseComObject
aber die Funktion scheint immer noch zu einen Verweis auf etwas halten. Hier ist, wie meine Funktion wie jetzt aussieht:
private void InjectFunction(IHTMLDocument2 document)
{
if (null == Document) throw new Exception("Cannot access current document's HTML or document is not an HTML.");
try
{
IHTMLDocument3 doc3 = document as IHTMLDocument3;
IHTMLElementCollection collection = doc3.getElementsByTagName("head");
IHTMLDOMNode head = collection.item(0);
IHTMLElement scriptElement = document.createElement("script");
IHTMLScriptElement script = (IHTMLScriptElement)scriptElement;
IHTMLDOMNode scriptNode = (IHTMLDOMNode)scriptElement;
script.text = CurrentFuncs;
head.AppendChild(scriptNode);
if (Document.InvokeScript(CurrentTestFuncName) == null) throw new Exception("Cannot inject Javascript code right now.");
Marshal.FinalReleaseComObject(scriptNode);
Marshal.FinalReleaseComObject(script);
Marshal.FinalReleaseComObject(scriptElement);
Marshal.FinalReleaseComObject(head);
Marshal.FinalReleaseComObject(collection);
Marshal.ReleaseComObject(doc3);
}
catch (Exception ex)
{
MessageBox.Show("Couldn't release!");
throw ex;
}
}
Die MessageBox.Show("Couldn't release!");
Linie wird nie getroffen, so gehe ich davon aus, alles richtig freigegeben worden ist. Hier ist, was ANTS zeigt:
Ich habe keine Ahnung, was das Standortcontainer Sache ist.
Wenn Sie COM-Objekte in einem Verfahren haben, so dass sie immer vor dem Wurf Ausnahmen aufzuräumen, da sie kann nicht bereinigt werden, nachdem die Ausnahme ausgelöst wurde ... – prprcupofcoffee