O Response.End () é considerado prejudicial?

Este Artigo da Response.End() Conhecimento diz que o Response.End() do ASP.NET aborta um thread.

Refletor mostra que se parece com isso:

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

Isso parece muito duro para mim. Como diz o artigo da base de conhecimento, qualquer código no aplicativo após Response.End() não será executado, e isso viola o princípio de menor espanto. É quase como Application.Exit() em um aplicativo WinForms. A exceção de interrupção de encadeamento causada por Response.End() não é alcançável, portanto, cercar o código em uma tryfinally não satisfaz.

Isso me faz pensar se devo sempre evitar Response.End() .

Alguém pode sugerir, quando devo usar Response.End() , quando Response.Close() e quando HttpContext.Current.ApplicationInstance.CompleteRequest() ?

ref: input do blog de Rick Strahl .


Com base na input que recebi, minha resposta é sim, Response.End é prejudicial , mas é útil em alguns casos limitados.

  • use Response.End() como um lance não-pesquisável, para finalizar imediatamente o HttpResponse em condições excepcionais. Pode ser útil durante a debugging também. Evite Response.End() para completar as respostas de rotina .
  • use Response.Close() para fechar imediatamente a conexão com o cliente. De acordo com essa postagem do blog do MSDN , esse método não se destina ao processamento normal de solicitações HTTP. É altamente improvável que você tenha um bom motivo para chamar esse método.
  • use CompleteRequest() para finalizar uma solicitação normal. CompleteRequest faz com que o pipeline do ASP.NET avance para o evento EndRequest , após a conclusão do evento atual HttpApplication . Então, se você chamar CompleteRequest , em seguida, escrever algo mais para a resposta, a gravação será enviada ao cliente.

Edit – 13 de abril de 2011

Mais clareza está disponível aqui:
– Post útil no Blog da MSDN
– Análise útil por Jon Reid

   

Se você tiver empregado um registrador de exceções em seu aplicativo, ele será diluído com as ThreadAbortException s dessas chamadas benignas de Response.End() . Acho que essa é a maneira da Microsoft dizer “Pare com isso!”.

Eu só usaria Response.End() se houvesse alguma condição excepcional e nenhuma outra ação fosse possível. Talvez então, registrar essa exceção possa indicar um aviso.

TL; DR

Inicialmente, recomendei que você simplesmente substituísse todas as suas chamadas para [Response.End] com chamadas […] CompleteRequest (), mas se quiser evitar o processamento de postback e renderização em html, será necessário adicionar [.. .] substitui também.

Jon Reid , “Análise Final”


Por MSDN, Jon Reid e Alain Renon:

Desempenho do ASP.NET – Gerenciamento de Exceções – Código de Escrita que Evita Exceções

Os methods Server.Transfer, Response.Redirect, Response.End levantam exceções. Cada um desses methods chama internamente Response.End. A chamada para Response.End, por sua vez, causa uma exceção ThreadAbortException .

Solução ThreadAbortException

HttpApplication.CompleteRequest () define uma variável que faz com que o encadeamento ignore a maioria dos events no pipeline de evento HttpApplication [-] e não na cadeia de events Page, mas na cadeia de events do Aplicativo.

crie uma variável de nível de class que sinalize se a Página terminar e, em seguida, verifique a variável antes de processar seus events ou renderizar sua página. […] Eu recomendaria apenas sobrescrevendo os methods RaisePostBackEvent e Render

Response.End e Response.Close não são usados ​​no processamento de solicitação normal quando o desempenho é importante. Response.End é um meio conveniente e pesado de encerrar o processamento de solicitações com uma penalidade de desempenho associada. Response.Close é para o término imediato da resposta HTTP no nível do IIS / soquete e causa problemas com coisas como KeepAlive.

O método recomendado para finalizar uma solicitação do ASP.NET é HttpApplication.CompleteRequest. Tenha em mente que a renderização do ASP.NET precisará ser ignorada manualmente, pois o HttpApplication.CompleteRequest ignora o restante do pipeline de aplicativo do IIS / ASP.NET, não o pipeline de página do ASP.NET (que é um estágio no pipeline do aplicativo).


Código

Copyright © 2001-2007, C6 Software, Inc , o melhor que eu poderia dizer.


Referência

HttpApplication.CompleteRequest

Faz com que o ASP.NET ignore todos os events e a filtragem na cadeia de execução do pipeline HTTP e execute diretamente o evento EndRequest.

Response.End

Esse método é fornecido apenas para compatibilidade com o ASP – ou seja, para compatibilidade com a tecnologia de programação da Web baseada em COM que precedeu o ASP.NET. ASP.NET.preceded. [Enfase adicionada]

Response.Close

Esse método finaliza a conexão com o cliente de maneira abrupta e não se destina ao processamento normal de solicitações HTTP . [Enfase adicionada]

Esta questão aparece no topo de todas as buscas no google por informações sobre resposta. Então, para outras buscas como eu, que desejam postar CSV / XML / PDF, etc, em resposta a um evento sem renderizar toda a página ASPX, é assim que eu faço . (replace os methods de renderização é excessivamente complexo para uma tarefa tão simples 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() 

Na questão de “Eu ainda não sei a diferença entre Response.Close e CompleteRequest ()” eu diria:

Não prefira CompleteRequest (), não use Response.Close ().

Veja o artigo a seguir para um resumo bem feito deste caso.

Esteja ciente de que, mesmo depois de chamar CompleteRequest (), algum texto (por exemplo, redregado do código ASPX) seria anexado ao stream de saída de resposta. Você pode evitá-lo substituindo os methods Render e RaisePostBackEvent, conforme descrito no artigo a seguir .

BTW: Eu concordo com a prevenção de usar Response.End (), especialmente ao gravar dados no stream http para emular o download de arquivos. Usamos o Response.End () no passado até que nosso arquivo de log ficou cheio de ThreadAbortExceptions.

Eu não concordo com a afirmação ” Resposta.End é prejudicial “. Definitivamente não é prejudicial. Response.End faz o que diz; termina a execução da página. Usar o refletor para ver como ele foi implementado deve ser visto apenas como instrutivo.


Minha recomendação 2cent
EVITE usar Response.End() como stream de controle.
Use o Response.End() se precisar parar a execução da solicitação e esteja ciente de que (normalmente) * nenhum código será executado após esse ponto.


* Response.End() e ThreadAbortException s.

Response.End() lança um ThreadAbortException como parte de sua implementação atual (conforme observado pelo OP).

ThreadAbortException é uma exceção especial que pode ser detectada, mas será automaticamente levantada novamente no final do bloco catch.

Para ver como escrever código que deve lidar com ThreadAbortExceptions, consulte a resposta do @Mehrdad ao SO Como posso detectar um threadabortexception em um bloco finally no qual ele faz referência ao Método RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup e às Regiões de Execução Restrita


O artigo de Rick Strahl mencionado é instrutivo, e certifique-se de ler os comentários também. Note que o problema de Strahl era específico. Ele queria obter os dados para o cliente (uma imagem) e, em seguida, processar a atualização do database de rastreamento de ocorrências que não reduzia a velocidade da veiculação da imagem, o que fez com que o problema de fazer algo depois de Response.End fosse chamado.

Eu nunca considerei usar Response.End () para controlar o stream do programa.

No entanto, Response.End () pode ser útil, por exemplo, ao servir arquivos para um usuário.

Você gravou o arquivo para a resposta e não deseja que mais nada seja adicionado à resposta, pois isso pode corromper o arquivo.

Eu usei Response.End () no ASP .NET e clássico para finalizar com força as coisas antes. Por exemplo, eu uso quando há uma quantidade certiana de tentativas de login. Ou quando uma página segura está sendo acessada de um login não autenticado (exemplo aproximado):

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

Ao servir arquivos para um usuário eu usaria um Flush, o End pode causar problemas.

Eu usei apenas Response.End () como um mecanismo de teste / debugging

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

A julgar pelo que você postou em termos de pesquisa, eu diria que seria um projeto ruim se exigisse Response.End