Dieser KB-Artikel besagt, dass ASP.NET Response.End()
einen Thread abbricht.
Reflektor zeigt, dass es so aussieht:
public void End()
{
if (this._context.IsInCancellablePeriod)
{
InternalSecurityPermissions.ControlThread.Assert();
Thread.CurrentThread.Abort(new HttpApplication.CancelModuleException(false));
}
else if (!this._flushing)
{
this.Flush();
this._ended = true;
if (this._context.ApplicationInstance != null)
{
this._context.ApplicationInstance.CompleteRequest();
}
}
}
Das scheint mir ziemlich hart zu sein. Wie der KB-Artikel sagt, wird kein Code in der folgenden App Response.End()
ausgeführt, was gegen das Prinzip des geringsten Erstaunens verstößt. Es ist fast wie Application.Exit()
in einer WinForms-App. Die durch verursachte Thread-Abbruch-Ausnahme Response.End()
ist nicht abfangbar, sodass das Umgeben des Codes in einem try
... finally
nicht zufriedenstellend ist.
Ich frage mich, ob ich es immer vermeiden sollte Response.End()
.
Kann jemand vorschlagen, wann ich Response.End()
wann Response.Close()
und wann verwenden soll HttpContext.Current.ApplicationInstance.CompleteRequest()
?
Ref: Rick Strahls Blogeintrag .
Basierend auf den Eingaben, die ich erhalten habe, lautet meine Antwort: Ja, Response.End
ist schädlich , aber in einigen begrenzten Fällen nützlich.
- Verwenden Sie
Response.End()
als nicht fangbarer Wurf, um dieHttpResponse
in außergewöhnlichen Bedingungen sofort zu beenden . Kann auch beim Debuggen hilfreich sein. Vermeiden SieResponse.End()
routinemäßige Antworten . - Verwenden Sie
Response.Close()
diese Option, um die Verbindung zum Client sofort zu schließen. Gemäß diesem MSDN-Blogbeitrag ist diese Methode nicht für die normale Verarbeitung von HTTP-Anforderungen vorgesehen. Es ist höchst unwahrscheinlich, dass Sie einen guten Grund haben, diese Methode aufzurufen. - Verwenden Sie
CompleteRequest()
diese Option, um eine normale Anforderung zu beenden.CompleteRequest
bewirkt, dass die ASP.NET-PipelineEndRequest
nach Abschluss des aktuellenHttpApplication
Ereignisses zum Ereignis springt . Wenn Sie also anrufenCompleteRequest
und dann etwas mehr in die Antwort schreiben, wird der Schreibvorgang an den Client gesendet.
Bearbeiten - 13. April 2011
Weitere Klarheit finden Sie hier:
- Nützlicher Beitrag im MSDN-Blog
- Nützliche Analyse von Jon Reid
Response.End
ThreadAbortException
ganz gut.Response.Redirect
undServer.Transfer
beide rufen anResponse.End
und sollten auch vermieden werden.Antworten:
Wenn Sie in Ihrer App einen Ausnahmeprotokollierer verwendet haben, wird dieser mit dem
ThreadAbortException
s dieser harmlosenResponse.End()
Anrufe verwässert . Ich denke, dies ist die Art von Microsoft, "Knock it off!" Zu sagen.Ich würde es nur verwenden,
Response.End()
wenn es einen außergewöhnlichen Zustand gäbe und keine andere Aktion möglich wäre. Vielleicht weist das Protokollieren dieser Ausnahme dann tatsächlich auf eine Warnung hin.quelle
TL; DR
Per MSDN, Jon Reid und Alain Renon:
ASP.NET-Leistung - Ausnahmeverwaltung - Schreiben Sie Code, der Ausnahmen vermeidet
ThreadAbortException-Lösung
Response.End und Response.Close werden bei der normalen Anforderungsverarbeitung nicht verwendet, wenn die Leistung wichtig ist. Response.End ist ein praktisches und hartnäckiges Mittel zum Beenden der Anforderungsverarbeitung mit einer damit verbundenen Leistungseinbuße. Response.Close dient zum sofortigen Beenden der HTTP-Antwort auf IIS- / Socket-Ebene und verursacht Probleme mit Dingen wie KeepAlive.
Die empfohlene Methode zum Beenden einer ASP.NET-Anforderung ist HttpApplication.CompleteRequest. Beachten Sie, dass das ASP.NET-Rendering manuell übersprungen werden muss, da HttpApplication.CompleteRequest den Rest der IIS / ASP.NET-Anwendungspipeline überspringt, nicht die ASP.NET-Seitenpipeline (die eine Stufe in der App-Pipeline darstellt).
Code
Copyright © 2001-2007, C6 Software, Inc, so gut ich es beurteilen konnte.
Referenz
HttpApplication.CompleteRequest
Response.End
Antwort. Schließen
quelle
Diese Frage wird oben in allen Google-Suchanfragen nach Informationen zu response.end angezeigt. Für andere Suchanfragen wie mich, die CSV / XML / PDF usw. als Antwort auf ein Ereignis veröffentlichen möchten, ohne die gesamte ASPX-Seite zu rendern, gehe ich folgendermaßen vor . (Das Überschreiben der Rendermethoden ist für eine so einfache Aufgabe IMO zu komplex.)
quelle
Zu der Frage "Ich kenne den Unterschied zwischen Response.Close und CompleteRequest () immer noch nicht" würde ich sagen:
Bevorzugen Sie CompleteRequest (), verwenden Sie nicht Response.Close ().
Im folgenden Artikel finden Sie eine ausführliche Zusammenfassung dieses Falls.
Beachten Sie, dass auch nach dem Aufruf von CompleteRequest () Text (z. B. aus ASPX-Code abgeleitet) an den Antwortausgabestream angehängt wird. Sie können dies verhindern, indem Sie die Methoden Render und RaisePostBackEvent überschreiben, wie im folgenden Artikel beschrieben .
Übrigens: Ich bin damit einverstanden, die Verwendung von Response.End () zu verhindern, insbesondere wenn Daten in den http-Stream geschrieben werden, um den Dateidownload zu emulieren. Wir haben in der Vergangenheit Response.End () verwendet, bis unsere Protokolldatei voller ThreadAbortExceptions war.
quelle
Ich bin mit der Aussage " Response.End is schädlich " nicht einverstanden . Es ist definitiv nicht schädlich. Response.End macht, was es sagt; Es beendet die Ausführung der Seite. Die Verwendung eines Reflektors, um zu sehen, wie er implementiert wurde, sollte nur als lehrreich angesehen werden.
Meine 2-Cent-Empfehlung
VERMEIDEN die Verwendung
Response.End()
als Kontrollfluss. Verwenden Sie dieseOption ,
Response.End()
wenn Sie die Ausführung von Anforderungen stoppen müssen und sich darüber im Klaren sind, dass (normalerweise) * kein Code über diesen Punkt hinaus ausgeführt wird.*
Response.End()
und ThreadAbortException s.Response.End()
löst eine ThreadAbortException als Teil der aktuellen Implementierung aus (wie von OP angegeben).Informationen zum Schreiben von Code, der sich mit ThreadAbortExceptions befassen muss, finden Sie in der Antwort von @ Mehrdad auf SO. Wie kann ich eine Threadabortexception in einem finally-Block erkennen, in dem er auf die RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup-Methode und eingeschränkte Ausführungsbereiche verweist ?
Der erwähnte Artikel von Rick Strahl ist lehrreich und lesen Sie auch die Kommentare. Beachten Sie, dass Strahls Problem spezifisch war. Er wollte die Daten an den Client weiterleiten (ein Bild) und dann die Aktualisierung der Hit-Tracking-Datenbank verarbeiten, die die Bereitstellung des Bildes nicht verlangsamte, was ihn zum Problem machte, etwas zu tun, nachdem Response.End aufgerufen worden war.
quelle
Ich habe nie darüber nachgedacht, Response.End () zur Steuerung des Programmflusses zu verwenden.
Response.End () kann jedoch beispielsweise beim Bereitstellen von Dateien an einen Benutzer hilfreich sein.
Sie haben die Datei in die Antwort geschrieben und möchten nicht, dass der Antwort etwas anderes hinzugefügt wird, da dies Ihre Datei beschädigen kann.
quelle
Ich habe Response.End () sowohl in .NET als auch in Classic ASP verwendet, um Dinge zuvor zwangsweise zu beenden. Zum Beispiel verwende ich es, wenn es eine bestimmte Anzahl von Anmeldeversuchen gibt. Oder wenn eine sichere Seite von einem nicht authentifizierten Login aus aufgerufen wird (grobes Beispiel):
Wenn ich einem Benutzer Dateien bereitstelle, würde ich einen Flush verwenden. Das Ende kann Probleme verursachen.
quelle
Ich habe nur Response.End () als Test- / Debugging-Mechanismus verwendet
Nach dem zu urteilen, was Sie in Bezug auf die Forschung gepostet haben, würde ich sagen, dass es ein schlechtes Design wäre, wenn es Response.End erfordern würde
quelle
Auf klassischem Asp hatte ich bei einigen Ajax-Aufrufen einen TTFB (Time To First Byte) von 3 bis 10 Sekunden, viel größer als der TTFB auf normalen Seiten mit viel mehr SQL-Aufrufen.
Der zurückgegebene Ajax war ein HTML-Segment, das in die Seite eingefügt werden sollte.
Der TTFB war einige Sekunden länger als die Renderzeit.
Wenn ich nach dem Rendern ein response.end hinzufügte, wurde der TTFB stark reduziert.
Ich könnte den gleichen Effekt erzielen, indem ich ein "</ body> </ html>" ausgeben würde, aber dies funktioniert wahrscheinlich nicht bei der Ausgabe von json oder xml. hier wird response.end benötigt.
quelle