Ich hatte eine ähnliche Frage, und die Antworten hier gaben mir nicht die Informationen, die ich brauchte. Obwohl es also eine akzeptierte Antwort gibt, werde ich hinzufügen, was ich gelernt habe, um dem Nächsten zu helfen.
1) Wie in einigen der anderen Antworten erwähnt, können Sie using
für die Streams, die von HttpWebRequest/WebRequest zurückgegeben werden. Dies ist nur gut Standard c# Programmierung.
Aber es nicht wirklich auf die OP-Frage (oder meine), die über die Beseitigung der HttpWebRequest-Objekt selbst war.
2) Trotz der Tatsache, dass die Funktion zur Erfassung einer HttpWebRequest "Create" heißt, gibt es keinen passenden Destroy-, Close-, Dispose- oder sonstigen Mechanismus, um die Ressourcen des erstellten Objekts freizugeben.
Dies ist im Grunde die derzeit akzeptierte Antwort.
3) Aber alle Antworten hier implizieren, dass es (abgesehen von den Strömen) nichts Wichtiges mehr gibt, das in der Gegend herumliegt. braucht geschlossen werden. Und das ist nicht ganz richtig.
Verwendung von ProcMon können Sie die TCP Connect
, TCP Send
y TCP Receive
die auftreten, wenn Sie die GetResponse()
. Das ist es, was ich erwarten würde, zu sehen. Aber wann ist die TCP Disconnect
auftreten? Ich bin davon ausgegangen, dass dies entweder nach dem Empfang der Antwort oder schlimmstenfalls, wenn das Objekt GC'ed wird, geschehen würde. Aber die Realität ist interessanter.
Stattdessen bleibt die TCP-Verbindung nach dem Anruf noch genau 2 Minuten lang aktiv. Mein erster Gedanke war, dass es nur so lange dauert, bis der GC sich damit befasst, aber nein. Sie können dort in einer GC.Collect()-Schleife für diese 2 Minuten sitzen, und es wird nicht losgelassen, bis die 2 Minuten vorbei sind. Dies hält die Verbindung sowohl auf dem Client als auch auf dem Server offen und verursacht (etwas) zusätzlichen Netzwerkverkehr für diese 2 Minuten, um die Verbindung aufrechtzuerhalten.
Interessant ist auch, dass der Aufruf von "Create" nicht unbedingt bedeutet, dass eine weitere TCP-Verbindung hergestellt wird. Betrachten Sie zum Beispiel dies:
static void Doit(string domain)
{
HttpWebRequest hr = (HttpWebRequest)WebRequest.Create(domain);
using (HttpWebResponse response = (HttpWebResponse)hr.GetResponse())
using (Stream receiveStream = response.GetResponseStream())
using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8))
Console.WriteLine(readStream.ReadToEnd());
}
Wenn ich das jetzt mit aufrufe:
Doit("http://www.foo.bar");
Es wird 1 TCP-Verbindung hergestellt. Sie bleibt für 2 Minuten aktiv (oder bis das Programm beendet wird). Aber was ist, wenn ich dies tue:
Doit("http://www.foo.bar");
Thread.Sleep(20000);
Doit("http://www.foo.bar");
Jetzt wird 1 Verbindung für den ersten Anruf hergestellt, dann Wiederverwendung diese Verbindung für den zweiten Anruf. Das bedeutet, dass die TCP-Verbindung insgesamt 2:20 Minuten lang aktiv bleibt. Obwohl wir also "Create" aufrufen, wird die Verbindung nicht von Grund auf neu erstellt.
Meistens ist das eine gute Sache. Die Herstellung einer Verbindung (insbesondere einer HTTPS-Verbindung) kann ein teurer Prozess sein. Ein System, das dies automatisch für Sie vermeidet, ist (wahrscheinlich) eine gute Sache. Auf diese Weise können Sie auf effiziente Weise die HTML-Datei für eine Webseite abrufen und dann alle zugehörigen Unterstützungsdateien (css, img-Dateien usw.), ohne jedes Mal den Verbindungsprozess durchlaufen zu müssen.
Was aber, wenn der Server, mit dem Sie sich verbinden wollen, nur eine begrenzte Anzahl von Verbindungen unterstützt? Wenn eine Verbindung ohne triftigen Grund bestehen bleibt, könnte das ein echtes Problem darstellen. Oder vielleicht können Sie aus Sicherheitsgründen die Verbindungen nicht so lange offen lassen? Vielleicht sind Sie aber auch einfach nur pingelig und wollen das Ding abschalten, sobald Sie damit fertig sind.
Für diese Fälle können Sie experimentieren mit HttpWebRequest.KeepAlive
. Diese Einstellung auf false
(der Standardwert ist true
) führt dazu, dass jedes der obigen Beispiele eine eigene Verbindung verwendet und diese beendet wird, sobald Sie fertig sind. Der gesamte Vorgang "Verbinden/Senden/Empfangen/Trennen" kann so in weniger als einer Sekunde abgeschlossen werden.
ZU IHRER INFORMATION:
- Sie können zwar WebRequest.InitializeLifetimeService verwenden, um eine ILease zu erhalten, aber das Ändern der Werte für den Lease hat hier keine Auswirkungen auf die Timeouts.
- Anstelle von WebRequest können Sie auch WebClient verwenden, der Dispose unterstützt. Die zugrunde liegende TCP-Verbindung bleibt jedoch auch nach dem Aufruf von Dispose noch 2 Minuten lang bestehen.
Zusammengefasst: Die Aussage, dass Sie sich keine Gedanken über das Herunterfahren eines HttpWebClients machen müssen, mag im Allgemeinen zutreffen, aber es gibt Auswirkungen, die Sie beachten sollten. Es gibt gute Gründe für dieses Verhalten, aber Sie können nicht entscheiden, ob dies für Ihre spezielle Anwendung gut ist, wenn Sie nicht wissen, dass es geschieht.
FWIW