Ten artykuł KB mówi, że ASP.NET Response.End()
przerywa wątek.
Odbłyśnik pokazuje, że wygląda to tak:
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();
}
}
}
Wydaje mi się to dość trudne. Jak mówi artykuł KB, żaden kod w poniższej aplikacji Response.End()
nie zostanie wykonany, co narusza zasadę najmniejszego zdziwienia. To prawie jak Application.Exit()
w aplikacji WinForms. Wyjątek przerwania wątku spowodowany przez Response.End()
nie jest możliwy do złapania, więc otoczenie kodu w try
... finally
nie spełni.
Zastanawiam się, czy zawsze powinienem tego unikać Response.End()
.
Czy ktoś może zasugerować, kiedy powinienem użyć Response.End()
, kiedy Response.Close()
i kiedy HttpContext.Current.ApplicationInstance.CompleteRequest()
?
ref: wpis na blogu Ricka Strahla .
Na podstawie otrzymanych informacji moja odpowiedź brzmi: tak, Response.End
jest szkodliwa , ale jest przydatna w niektórych ograniczonych przypadkach.
- użyć
Response.End()
jako rzut niemożliwy do złapania, aby natychmiast zakończyćHttpResponse
wyjątkowe warunki. Może być przydatny również podczas debugowania. UnikajResponse.End()
rutynowych odpowiedzi . - użyj,
Response.Close()
aby natychmiast zamknąć połączenie z klientem. Zgodnie z tym postem na blogu MSDN ta metoda nie jest przeznaczona do normalnego przetwarzania żądań HTTP. Jest bardzo mało prawdopodobne, że powinieneś nazwać tę metodę. - użyj,
CompleteRequest()
aby zakończyć normalne żądanie.CompleteRequest
powoduje, że potok ASP.NET przeskakuje doEndRequest
zdarzenia po zakończeniu bieżącegoHttpApplication
zdarzenia. Więc jeśli zadzwoniszCompleteRequest
, a następnie napisz coś więcej w odpowiedzi, zapis zostanie wysłany do klienta.
Edycja - 13 kwietnia 2011 r
Dalsza przejrzystość jest dostępna tutaj:
- Przydatny post na blogu MSDN
- Przydatna analiza autorstwa Jona Reida
Response.End
ThreadAbortException
.Response.Redirect
iServer.Transfer
zarówno połączeniaResponse.End
i należy również unikać.Odpowiedzi:
Jeśli w swojej aplikacji zastosowano rejestrator wyjątków, zostanie on rozwodniony za pomocą
ThreadAbortException
s tych łagodnychResponse.End()
połączeń. Myślę, że w ten sposób Microsoft mówi „Odrzuć to!”.Używałbym tylko,
Response.End()
gdyby istniał jakiś wyjątkowy warunek i żadne inne działanie nie było możliwe. Może wtedy zarejestrowanie tego wyjątku może faktycznie oznaczać ostrzeżenie.źródło
TL; DR
Według MSDN, Jon Reid i Alain Renon:
Wydajność ASP.NET - Zarządzanie wyjątkami - Napisz kod, który omija wyjątki
Rozwiązanie ThreadAbortException
Response.End i Response.Close nie są używane w normalnym przetwarzaniu żądań, gdy ważna jest wydajność. Response.End to wygodny, ciężki sposób na zakończenie przetwarzania żądania z powiązanym ograniczeniem wydajności. Odpowiedź.Zamknij służy do natychmiastowego zakończenia odpowiedzi HTTP na poziomie IIS / gniazda i powoduje problemy z takimi rzeczami, jak KeepAlive.
Zalecaną metodą zakończenia żądania ASP.NET jest HttpApplication.CompleteRequest. Należy pamiętać, że renderowanie ASP.NET będzie musiało zostać pominięte ręcznie, ponieważ HttpApplication.CompleteRequest pomija resztę potoku aplikacji IIS / ASP.NET, a nie potok strony ASP.NET (który jest jednym z etapów potoku aplikacji).
Kod
Copyright © 2001-2007, C6 Software, Inc, co mogłem najlepiej powiedzieć.
Odniesienie
HttpApplication.CompleteRequest
Odpowiedź. Koniec
Odpowiedź.Zamknij
źródło
To pytanie pojawia się u góry wszystkich wyszukiwań w Google, aby uzyskać informacje o odpowiedzi. Tak więc w przypadku innych wyszukiwań, takich jak ja, które chcą opublikować CSV / XML / PDF itp. W odpowiedzi na zdarzenie bez renderowania całej strony ASPX, tak to robię . (przesłanianie metod renderowania jest zbyt skomplikowane jak na tak proste zadanie IMO)
źródło
Na pytanie „Nadal nie znam różnicy między Response.Close a CompleteRequest ()” powiedziałbym:
Wolisz CompleteRequest (), nie używaj Response.Close ().
Zapoznaj się z poniższym artykułem, aby uzyskać dobrze wykonane podsumowanie tej sprawy.
Należy pamiętać, że nawet po wywołaniu CompleteRequest () do tekstu wyjściowego odpowiedzi zostanie dołączony jakiś tekst (np. Ponownie odczytany z kodu ASPX). Można temu zapobiec, zastępując metody Render i RaisePostBackEvent zgodnie z opisem w poniższym artykule .
BTW: Zgadzam się z zapobieganiem używaniu Response.End (), szczególnie przy zapisywaniu danych do strumienia http w celu emulacji pobierania plików. W przeszłości używaliśmy Response.End (), dopóki nasz plik dziennika nie zapełnił się wyjątkami ThreadAbortException.
źródło
Nie zgadzam się ze stwierdzeniem „ Odpowiedź. Koniec jest szkodliwy ”. To zdecydowanie nie jest szkodliwe. Response.End robi to, co mówi; kończy wykonywanie strony. Używanie reflektora do sprawdzenia, w jaki sposób został zaimplementowany, należy traktować jedynie jako pouczające.
Moje 2-procentowe zalecenie
UNIKAJ używania
Response.End()
jako przepływu kontrolnego.DO użycie
Response.End()
jeśli trzeba zatrzymać wykonanie żądań i mieć świadomość, że (zazwyczaj) * kod nie wykona przeszłości tego miejsca.*
Response.End()
i ThreadAbortException s.Response.End()
zgłasza wyjątek ThreadAbortException w ramach jego bieżącej implementacji (jak zauważył OP).Aby zobaczyć, jak napisać kod, który musi radzić sobie z Wyjątkami ThreadAbort, zobacz odpowiedź @ Mehrdada na SO. Jak mogę wykryć wyjątek typu Threadabort w ostatnim bloku, w którym odwołuje się on do metody RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup i regionów ograniczonego wykonania
Wspomniany artykuł Ricka Strahla jest pouczający i koniecznie przeczytaj komentarze. Zauważ, że problem Strahla był specyficzny. Chciał przekazać dane klientowi (obraz), a następnie przetworzyć aktualizację bazy danych śledzenia trafień, co nie spowolniło wyświetlania obrazu, co sprawiło, że miał problem z zrobieniem czegoś po wywołaniu odpowiedzi.
źródło
Nigdy nie rozważałem użycia Response.End () do sterowania przebiegiem programu.
Jednak Response.End () może być przydatny na przykład podczas udostępniania plików użytkownikowi.
Zapisałeś plik do odpowiedzi i nie chcesz, aby do odpowiedzi dodawano nic innego, ponieważ może to spowodować uszkodzenie pliku.
źródło
Używałem Response.End () zarówno w .NET, jak i Classic ASP, aby wcześniej skutecznie wymusić zakończenie. Na przykład używam go, gdy istnieje pewna liczba prób logowania. Lub gdy uzyskuje się dostęp do bezpiecznej strony z nieuwierzytelnionego logowania (szorstki przykład):
Podczas udostępniania plików użytkownikowi używałbym koloru, koniec może powodować problemy.
źródło
Użyłem tylko Response.End () jako mechanizmu testowania / debugowania
Sądząc z tego, co napisałeś w zakresie badań, powiedziałbym, że byłby to zły projekt, gdyby wymagał odpowiedzi.
źródło
W klasycznym asp miałem TTFB (czas do pierwszego bajtu) wynoszący od 3 do 10 sekund w przypadku niektórych wywołań ajax, znacznie większy niż TTFB na zwykłych stronach z większą liczbą wywołań SQL.
Zwrócony ajax był fragmentem HTML, który ma zostać wstrzyknięty na stronę.
TTFB był o kilka sekund dłuższy niż czas renderowania.
Jeśli dodałem odpowiedź. Koniec po renderowaniu, TTFB został znacznie zmniejszony.
Mógłbym uzyskać ten sam efekt, emitując „</body> </html>”, ale to prawdopodobnie nie działa, gdy wypisujesz json lub xml; tutaj potrzebna jest odpowiedź. koniec.
źródło