Rekursive HTTP-Aufrufe weisen ein unterschiedliches Verhalten in der IDE gegenüber der ausführbaren ausführbaren Datei auf

8

Der Code führt HTTP-Aufrufe an eine exponierte Darstellung eines SVN-Baums aus. Es analysiert dann den HTML-Code und fügt Dateien zum Nachschlagen hinzu, um den Benutzer herunterzuziehen und an den Benutzer zu senden. Dies wird in einer WPF-Anwendung durchgeführt. Unten ist der Code zusammen mit einem Bild, das die Verzeichnisstruktur zeigt.

%Vor%

Erste Entschuldigung für den langwierigen Codeblock; Ich wollte jedoch sicherstellen, dass die vollständige Methode verstanden wurde. Das Problem, das vorhanden ist, ist nur anwendbar, wenn die generierte ausführbare Datei Release außerhalb der IDE verwendet wird. Wenn der Build Release in der IDE ausgeführt wird, funktioniert er ohne Probleme.

Außerdem existiert das Problem nicht, wenn das generierte Debug Build außerhalb der IDE oder innerhalb der IDE ausgeführt wird. es funktioniert in beiden Szenarien entsprechend.

Das Problem besteht darin, dass die rekursiven Aufrufe den Code nach der Rekursionsmethode anhalten. Es wird keine Ausnahme innerhalb des Threads geworfen. Alles wird einfach gestoppt, bevor es in jedes Verzeichnis verschoben wird, wie in den anderen Builds.

Die Protokollzeilen des Builds Release sehen so aus ...

  

Initiierende Anfrage   [ Ссылка
  Antwort für Anfrage erhalten   [ Ссылка
  Abfragen von [beq /]
Suchen   Verzeichnis [beq /]
Initiieren   anfordern   [ Ссылка
  Antwort für Anfrage erhalten   [ Ссылка
  Abfragen von [core /]
Suchen   Verzeichnis [core /]
Initiieren   anfordern   [ Ссылка
  Antwort für Anfrage erhalten   [ Ссылка
  Befragung   [BEQ-Core% 20Library.vbs]
Hinzugefügt   Datei   [ Ссылка
  Abfragen von [Einzelfällen /]
  Verzeichnis suchen [one-offs /]
  Anfrage einleiten   [ Ссылка
  Antwort für Anfrage erhalten   [ Ссылка
  Das rekursive Auffinden von Skripts dauerte [6] s   [140] ms für [1]
Metadaten analysieren   nahm [0] m [0] s [906] ms für [1]
  Gesamtzeit nahm [0] m [7] s [46] ms

UPDATE:

Nach dem Hinzufügen von ungefähr 3 zusätzlichen Protokollzeilen während des Debuggens funktioniert es jetzt wie es sollte. Die offene Frage ist warum? Der Versuch, den Problemcode in einer separaten Anwendung zu isolieren, führt zu keinen negativen Ergebnissen.

Irgendwelche Ideen, warum das passieren würde?

UPDATE:

Das Ändern der Protokollzeilen, um eine falsche Methode aufzurufen, führte zu denselben Ergebnissen. Ich habe die Aufrufe der Faux-Methode und der Faux-Methode in der obigen Quelle, 1 am Eingang der Methode und 3 in der Nähe der Unterseite hinzugefügt. Die Anrufe selbst sind kommentiert, um das Auffinden zu erleichtern; Sie werden NICHT im eigentlichen Code kommentiert.

Wenn ich einen der 4 addierten Faux-Methodenaufrufe auskommentiere, wird er nicht funktionieren. Auch dies ist nur in Release über STRG + F5 oder außerhalb der IDE in ihrer Gesamtheit.

UPDATE:

Hinzugefügt .close () für die HtmlDocument instances per fubaar; Das gleiche Verhalten wird immer noch gezeigt.

UPDATE:

Explizite Aufrufe an den GC per fubaar hinzugefügt; Das gleiche Verhalten wird immer noch gezeigt.

    
Aaron McIver 21.06.2011, 17:41
quelle

3 Antworten

1

Ich habe bemerkt, dass Sie .close () nicht für die HtmlDocument-Instanzen aufrufen, die Sie erstellen - das wäre die erste Sache, die ich versuchen würde, um sicherzustellen, dass mshtml nach dem write () korrekt bereinigt wird >

Sie könnten auch versuchen, Ihre Liste von Dateinamen aus dem Html zu erstellen und das HtmlDocument freizugeben, bevor Sie in die Dateinamenliste zurückkehren - damit Sie keine ständig wachsende Anzahl von HtmlDocument-Instanzen erstellen - in einer reinen .NET-Welt Seien Sie ein Speicherproblem, aber wenn Sie mshtml und damit COM interop mit einbeziehen, ist es unsere Erfahrung, dass es sich oft lohnt, viel sorgfältiger zu gehen.

Als Bearbeitung hinzugefügt, da es für einen Kommentar zu lang war:

In unserer Wpf-App haben wir ein Problem mit der Verarbeitung einer großen Anzahl von HtmlDocument-Instanzen, wo WPF die Initialisierungs- / Beendigungsnachrichten von COM nicht routinemäßig pumpt. In unserer Implementierung führte dies zu einem Speicherverlust und möglichen COM-Fehlern. Das ist natürlich nicht das Verhalten, das Sie sehen, aber ich frage mich, ob es ein Problem mit dem COM-Interop geben könnte, das nicht in der Lage ist, richtig zu säubern. Es lohnt sich, diese Zeilen hinzuzufügen, wenn Sie Ihre COM-Objekte fertiggestellt haben (und vollständig freigegeben haben):

%Vor%

Dadurch werden COM-Interop-Objekte zur Finalizer-Warteschlange hinzugefügt (der Aufruf .Collect) und .NET wird dazu veranlasst, COM-Nachrichten zu pumpen (ein Nebeneffekt des Aufrufs WaitForPendingFinalizers).

Es ist ein bisschen eine Stich in die Dunkelheit, die ich weiß, aber das Zeug ist im Wesentlichen COM-Interop (obwohl es mit .NET-Objekten abgedeckt ist) und dies könnte das Problem sein.

    
fubaar 27.06.2011 22:19
quelle
1

Nicht sicher, ob das richtig ist, da es sich um reine Spekulation handelt. Die COM-API in mshtml.dll scheint nirgendwo dokumentiert zu sein, und die .Net-Wrapper sind hinsichtlich zulässiger Verhaltensweisen vage.

In der .NET-Dokumentation wird davon ausgegangen, dass Sie eine Instanz von erhalten HtmlDocument von einem gehosteten WebBrowser-Steuerelement. Es gibt nichts in der Dokumentation, das darauf hinweist, dass Sie eigene Instanzen erstellen sollten. Seien Sie immer vorsichtig bei Adaptermustern , da die zugrunde liegende Datenverwaltung bei unerwarteter Verwendung gefährdet sein könnte. Sie würden hoffen, dass Sie daran gehindert werden, dies zu tun, aber es könnte eine Unterlassung oder ein Artefakt davon sein, wie .net COM umschließt.

Die IHTMLElementCollection verweist direkt zurück auf das HtmlDocument. Wenn diese Klasse eine gemeinsam genutzte Instanz eines WebControls verwendet (Sie haben nie ein eigenes Web-Steuerelement erstellt, so dass die Implementierung dem Framework überlassen bleibt), wird die Auflistung ungültig, wenn sich das Dokument ändert.

Warum ändert sich das Verhalten zwischen Debug und Release zusammen mit der Protokollzeile? Keine Ahnung. Könnte alle möglichen interessanten Speicher / Cache-Verwaltung im Internet Explorer-Code sein. Ihre GC-Aufrufe betreffen nur den Wrapper, nicht den nativen IE-Code.

Erstellen Sie als Test eine Kopie der relevanten Listendaten, bevor Sie sie durchlaufen, damit Sie unter HtmlDocument keine Wiederverwendung mehr haben.

Ich denke immer noch, dass die Verwendung der API möglicherweise falsch ist und dass das Arbeiten mit dem WebControl möglicherweise die einzig korrekte Verwendung ist. Ich kann jedoch keine Dokumentation finden, die beschreibt, wie sich die COM-Schnittstellen in mshtml verhalten sollten (ich habe mehrere Webseiten gefunden, die darauf hinweisen, dass es sich um ein undokumentiertes SDK handelt).

    
Jim Rush 07.08.2011 14:50
quelle
1

Nur ein Gedanke, aber könnte Ihr Code durch eine Compiler-Optimierung negativ beeinflusst werden? Erhalten Sie immer noch den Fehler, wenn Sie die Optimierungen ausschalten?

    
Adam Jones 25.08.2011 17:19
quelle

Tags und Links