Es la Respuesta.End() considera perjudicial?


Este artículo de KB dice que ASP.NET ' s Response.End() aborta un hilo.

El reflector muestra que se ve así:

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();
        }
    }
}

Esto me parece bastante duro. Como dice el artículo de KB, cualquier código en la aplicación que siga a Response.End() no se ejecutará, y eso viola el principio de mínimo asombro. Es casi como Application.Exit() en una aplicación WinForms. La excepción de interrupción del subproceso causada por Response.End() no es catchable, por lo que rodea el código en un try...finally no satisfará.

Me hace preguntarme si siempre debería evitar Response.End().

¿Puede alguien sugerir, cuándo debo usar Response.End(), cuándo Response.Close() y cuándo HttpContext.Current.ApplicationInstance.CompleteRequest()?

Ref: La entrada del blog de Rick Strahl .


Basado en la entrada que he recibido, mi respuesta es, Sí, Response.End es perjudicial, pero es útil en algunos casos limitados.

  • use Response.End() como un lanzamiento inalcanzable, para terminar inmediatamente el HttpResponse en condiciones excepcionales. Puede ser útil durante depuración también. Evite Response.End() completar las respuestas de rutina.
  • use Response.Close() para cerrar inmediatamente la conexión con el cliente. Según esta entrada de blog de MSDN, este método no está destinado al procesamiento normal de solicitudes HTTP. Es muy poco probable que tenga una buena razón para llamar a este método.
  • use CompleteRequest() para finalizar una solicitud normal. CompleteRequest causa la ASP.NET canalización para saltar al evento EndRequest, después del evento actual HttpApplication completo. Así que si llamas CompleteRequest, entonces escribe algo más a la respuesta, la escritura será enviada al cliente.

Editar-13 de abril de 2011

Más claridad está disponible aquí:
- Entrada útil en el Blog de MSDN
- Análisis útil de Jon Reid

 194
Author: J0e3gan, 2009-07-06

8 answers

Si ha empleado un registrador de excepciones en su aplicación, se diluirá con los ThreadAbortExceptions de estas llamadas benignas Response.End(). Creo que esta es la manera de Microsoft de decir " Basta!".

Solo usaría Response.End() si hubiera alguna condición excepcional y no fuera posible ninguna otra acción. Tal vez entonces, registrar esta excepción podría indicar una advertencia.

 63
Author: spoulson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-06 18:06:53

TL; DR

Inicialmente había recomendado que simplemente reemplazara todas sus llamadas a [Respuesta.Fin] con [...] CompleteRequest () llama, pero si desea evitar procesamiento postback y renderizado html necesitarás agregar [...] anula como bien.

Jon Reid , "Análisis final"


Por MSDN, Jon Reid , y Alain Renon:

ASP.NET Rendimiento - Gestión de Excepciones-Escribir Código Que Evita Excepciones

El Servidor.Transferencia, Respuesta.Redireccionamiento, Respuesta.Métodos de fin todas las subidas salvedad. Cada uno de estos métodos llama internamente a la Respuesta.Final. La llamada a Respuesta.End, a su vez, causa una excepción ThreadAbortException.

ThreadAbortException Solution

HttpApplication.CompleteRequest() establece una variable que hace que el hilo saltar más allá de la mayoría de los eventos en la tubería de eventos HttpApplication [not] not el Cadena de eventos de la página, pero la cadena de eventos de la aplicación.

...

Crear una variable de nivel de clase que marca si la página debe terminar y luego compruebe la variable antes de procesar sus eventos o renderizar su página. [...] Yo recomendaría simplemente anular los métodos RaisePostBackEvent y Render

Respuesta.Fin y Respuesta.Cerrar no se utilizan en el procesamiento normal de solicitudes cuando el rendimiento es importante. Respuesta.Final es un conveniente, medios de mano dura de finalización del procesamiento de solicitudes con una penalización de rendimiento asociada. Respuesta.Close es para la terminación inmediata de la respuesta HTTP en el IIS / socket nivel y causa problemas con cosas como KeepAlive.

El método recomendado para terminar un ASP.NET la solicitud es HttpApplication.Solicitud completa. Tenga en cuenta que ASP.NET el renderizado tendrá para ser omitido manualmente desde HttpApplication.CompleteRequest se salta el resto de la canalización de aplicaciones IIS / ASP. NET, no el ASP.NET Canalización de página (que es una etapa en la canalización de aplicaciones).


Código

Copyright © 2001-2007, C6 Software, Inc lo mejor que pude decir.


Referencia

HttpApplication.CompleteRequest

Causas ASP.NET para omitir todos los eventos y el filtrado en la cadena de canalización HTTP de ejecución y ejecutar directamente el evento EndRequest.

Respuesta.End

Este método es sólo para la compatibilidad con ASP - es decir, para compatibilidad con la tecnología de programación web basada en COM que precedió ASP. NET. preceded ASP.NET. [Sin cursiva en el original]

Respuesta.Cerrar

Este método termina la conexión con el cliente de manera abrupta y es no está diseñado para el procesamiento normal de solicitudes HTTP. [Énfasis añadido]

 105
Author: user423430,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-10 20:06:17

Esta pregunta aparece cerca de la parte superior de todas las búsquedas de Google para obtener información sobre la respuesta.end so para otras búsquedas como yo que desean publicar CSV / XML / PDF, etc. en respuesta a un evento sin renderizar toda la página ASPX, así es como lo hago. (sobreescribir los métodos de renderizado es demasiado complejo para una tarea tan simple IMO)

// Add headers for a csv file or whatever
Response.ContentType = "text/csv"
Response.AddHeader("Content-Disposition", "attachment;filename=report.csv")
Response.AddHeader("Pragma", "no-cache")
Response.AddHeader("Cache-Control", "no-cache")

// Write the data as binary from a unicode string
Dim buffer As Byte()
buffer = System.Text.Encoding.Unicode.GetBytes(csv)
Response.BinaryWrite(buffer)

// Sends the response buffer
Response.Flush()

// Prevents any other content from being sent to the browser
Response.SuppressContent = True

// Directs the thread to finish, bypassing additional processing
HttpContext.Current.ApplicationInstance.CompleteRequest()
 92
Author: Jay Zelos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-21 10:19:53

Sobre la pregunta de "Todavía no sé la diferencia entre la Respuesta.Close and CompleteRequest()" Yo diría:

Prefiera CompleteRequest(), no use Response.Cerca().

Ver el siguiente artículo para un resumen bien hecho de este caso.

Tenga en cuenta que incluso después de llamar a CompleteRequest() algún texto (por ejemplo, redndered desde el código ASPX) se agregaría al flujo de salida de la respuesta. Puede evitarlo anulando Render y RaisePostBackEvent métodos descritos en el siguiente artículo.

Por cierto: Estoy de acuerdo con la prevención del uso de la respuesta.End (), especialmente cuando se escriben datos en el flujo http para emular la descarga de archivos. Hemos usado la Respuesta.End () en el pasado hasta que nuestro archivo de registro se llenó de ThreadAbortExceptions.

 10
Author: Jan Šotola,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-02 15:53:45

No estoy de acuerdo con la declaración " Respuesta.End is harmful". Definitivamente no es dañino. Respuesta.End hace lo que dice; termina la ejecución de la página. El uso de reflector para ver cómo se implementó solo debe verse como instructivo.


Mi Recomendación del 2cent
EVITE usando Response.End() como flujo de control.
HAGA use Response.End() si necesita detener la ejecución de la solicitud y tenga en cuenta que (normalmente)* ningún código se ejecutará después de ese punto.


* Response.End() y ThreadAbortException s.

Response.End() lanza una ThreadAbortException como parte de su implementación actual (como se indica en OP).

ThreadAbortException es una excepción especial que puede ser capturada, pero se levantará automáticamente de nuevo al final del bloque catch.

Para ver cómo escribir código que debe tratar con ThreadAbortExceptions, vea la respuesta de @Mehrdad a SO ¿Cómo puedo detectar una threadabortexception en un bloque final donde hace referencia a RuntimeHelpers.Executecodewith Guaranteedcleanup Method and Constrained Execution Regions


El artículo de Rick Strahl mencionado es instructivo, y asegúrese de leer los comentarios también. Nótese que el asunto de Strahl era específico. Quería obtener los datos al cliente (una imagen) y luego procesar la actualización de la base de datos de seguimiento de visitas que no ralentizara la entrega de la imagen, lo que hizo que su problema fuera hacer algo después Respuesta.Fin había sido llamado.

 9
Author: Robert Paulson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:37

Nunca he considerado usar la respuesta.End() para controlar el flujo del programa.

Sin embargo Respuesta.End() puede ser útil, por ejemplo, cuando se sirven archivos a un usuario.

Ha escrito el archivo en la respuesta y no desea que se agregue nada más a la respuesta, ya que puede dañar su archivo.

 4
Author: Fishcake,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-06 16:49:08

He usado Respuesta.End () tanto en.NET como en Classic ASP para terminar forzosamente las cosas antes. Por ejemplo, lo uso cuando hay una cantidad de intentos de inicio de sesión. O cuando se accede a una página segura desde un inicio de sesión no autenticado (ejemplo aproximado):

    if (userName == "")
    {
        Response.Redirect("......");
        Response.End();
    }
    else
    {
      .....

Al servir archivos a un usuario usaría un Flush, el Final puede causar problemas.

 2
Author: Tim Meers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-06 18:01:30

Solo he usado Respuesta.End () como mecanismo de prueba/depuración

<snip>
Response.Write("myVariable: " + myVariable.ToString());
Response.End();
<snip>

A juzgar por lo que ha publicado en términos de investigación, yo diría que sería un mal diseño si requiere Respuesta.End

 2
Author: Nathan Koop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-07-06 18:10:00