202 votes

Est La Réponse.Fin() considéré comme dangereux?

Cet Article dit que ASP.NET's Réponse.Fin() interrompt un thread.

Réflecteur montre qu'il ressemble à ceci:

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

Cela semble assez dure pour moi. Comme l'article le dit, tout le code dans l'application de Réponse suivants.Fin() ne sera pas exécuté, et qui viole le principe de moindre surprise. C'est presque comme Application.Exit() dans une application WinForms. L'abandon de thread exception provoquée par la Réponse.Fin() n'est pas catchable, si entourant le code dans un essai..enfin il ne peut pas satisfaire.

Il me fait me demander si je devrait toujours éviter de Réponse.Fin().

Quelqu'un peut-il suggérer, quand devrais-je utiliser la Réponse.End(), lorsque la Réponse.Close() et quand HttpContext.Actuel.ApplicationInstance.CompleteRequest()?

ref: Rick Strahl de l'entrée de blog.


D'après les commentaires que j'ai reçu, ma réponse est Oui, la Réponse.La fin est nuisible, mais il est utile dans certains cas limités.

  • utiliser la Réponse.Fin() comme une part insaisissable de jeter, de résilier immédiatement le HttpResponse dans des conditions exceptionnelles. Peut être utile lors du débogage. Éviter De Réponse.Fin() pour valider la routine de réponses.
  • utiliser la Réponse.Close() pour fermer immédiatement la connexion avec le client. Par cette MSDN billet de blog, cette méthode n'est pas prévu pour HTTP normal de traitement de la demande. Il est très peu probable que vous avez une bonne raison d'appeler cette méthode.
  • utilisation CompleteRequest() pour mettre fin à une requête normale. CompleteRequest causes du RÉSEAU "intermédiaires" pour passer à l'événement EndRequest, après que le courant HttpApplication événement se termine. Donc, si vous appelez CompleteRequest, puis d'écrire quelque chose de plus pour la réponse, l'écriture sera envoyé au client.

Edit - 13 Avril 2011

Une plus grande clarté est disponible ici:
- Utile post sur le Blog MSDN
- Analyse utile par Jon Reid

109voto

user423430 Points 1505

TL;DR

Au début, j'avais recommandé que vous devez simplement remplacer tous vos appels vers [Réponse.Fin] avec [...] CompleteRequest() appelle, mais si vous voulez éviter le traitement de publication et de rendu html, vous aurez besoin d'ajouter [...] remplace comme bien.

Jon Reid, "En Dernière Analyse"


Par MSDN, Jon Reid, et Alain Renon:

ASP.NET la Performance - Gestion des exceptions - Écrire du Code Qui Évite les Exceptions

Le Serveur.De Transfert, Réponse.Rediriger, La Réponse.Fin de méthodes à l'augmentation de des exceptions. Chacune de ces méthodes en interne, Réponse à un appel.Fin. L'appel à Réponse.Fin, à son tour, provoque une exception ThreadAbortException.

ThreadAbortException Solution

HttpApplication.CompleteRequest() définit une variable qui entraîne le thread passer au-delà de la plupart des événements dans le HttpApplication événement pipeline [--] pas La Page de l'événement de la chaîne, mais la Demande chaîne d'événements.

...

créer une classe de niveau variable que les drapeaux si la Page doit mettre fin et puis vérifiez la variable avant le traitement de vos événements ou de rendu de votre page. [...] Je recommande juste de substitution de la RaisePostBackEvent et de Rendre les méthodes de

Réponse.Fin et de la Réponse.À proximité ne sont pas utilisés dans des conditions normales de traitement de la demande lors de l' la performance est importante. Réponse.La fin est un moyen pratique de, lourde les moyens de la résiliation de traitement de la demande associée à une perte de performance. Réponse.Proche est l'arrêt immédiat de la réponse HTTP à l'IIS/socket le niveau et les causes des problèmes avec des choses comme le KeepAlive.

La méthode recommandée pour mettre fin à une ASP.NET la demande est HttpApplication.CompleteRequest. Gardez à l'esprit que ASP.NET le rendu sera pour être ignorée manuellement depuis HttpApplication.CompleteRequest ignore le reste de IIS/ASP.NET application pipeline, pas la ASP.NET Page pipeline (qui est une étape dans l'application de pipeline).


Code

Copyright © 2001-2007, C6 Software, Inc mieux que je pouvais dire.


Référence

HttpApplication.CompleteRequest

Causes ASP.NET pour contourner tous les événements et de filtrage dans le pipeline HTTP chaîne de l'exécution et l'exécuter directement le EndRequest événement.

Réponse.Fin

Cette méthode est fournie uniquement à des fins de compatibilité avec l'ASP-qui est, pour la compatibilité avec les COM-internet basé sur la technologie de programmation qui l'ont précédé ASP.NET.précédé ASP.NET. [Italiques ajoutés]

Réponse.Fermer

Cette méthode met fin à la connexion avec le client de manière abrupte et est pas prévu pour HTTP normal de traitement de la demande. [Italiques ajoutés]

104voto

Jay Zelos Points 789

Cette question apparaît près du haut de toutes les recherches sur google pour plus d'informations sur la réponse.fin donc pour d'autres recherches, comme moi, qui souhaitent publier CSV/XML/PDF etc en réponse à un événement sans le rendu de l'ensemble de la page ASPX, c'est comment je le fais. (remplace les méthodes de rendu est trop complexe pour une simple tâche de l'OMI)

// 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()

67voto

spoulson Points 13391

Si vous aviez utilisé un logger sur votre application, il sera diluée avec de l' ThreadAbortExceptions à partir de ces bénigne Response.End() des appels. Je pense que c'est Microsoft façon de dire "arrête!".

Je ne utiliser Response.End() s'il n'était pas en état exceptionnel, et aucune autre action n'a été possible. Alors, peut-être, la journalisation de cette exception peut effectivement indiquer un avertissement.

11voto

Jan Šotola Points 384

Sur la question de "je ne sais toujours pas la différence entre la Réponse.Fermer et CompleteRequest ()", je dirais:

Ne préférez CompleteRequest(), n'utilisez pas de Réponse.Close().

Voir l' article suivant pour un bien-fait le résumé de cette affaire.

Sachez que, même après l'appel de CompleteRequest() un peu de texte (par exemple redndered de code ASPX) devrait être annexée à la réponse au flux de sortie. Vous pouvez empêcher cela en remplaçant le Rendu et RaisePostBackEvent méthodes comme décrit dans l' article suivant.

BTW: je suis d'accord avec la prévention de l'utilisation de la Réponse.End(), en particulier lors de l'écriture des données dans le flux http pour émuler de téléchargement de fichiers. Nous avons utilisé la Réponse.Fin (la), dans le passé, jusqu'à ce que notre fichier journal est devenu plein de ThreadAbortExceptions.

9voto

Robert Paulson Points 10792

Je suis en désaccord avec l'énoncé "Réponse.La fin est nuisible". Ce n'est certainement pas dangereux. Réponse.Fin est ce qu'il dit; il se termine l'exécution de la page. À l'aide de réflecteur pour voir comment il a été mis en œuvre doit être considérée seulement comme instructif.


Mon 2cent Recommandation
ÉVITER l' utilisation de Response.End() que le contrôle de flux.
N' utilisez Response.End() si vous avez besoin d'arrêter l'exécution de la demande et être conscient que (généralement)* pas de code s'exécute-delà de ce point.


* Response.End() et ThreadAbortExceptions.

Response.End() jette un ThreadAbortException dans le cadre de son actuelle mise en œuvre (comme indiqué par l'OP).

ThreadAbortException est une exception spéciale, qui peut être pris, mais il sera automatiquement soulevé de nouveau à la fin du bloc catch.

Pour voir comment écrire du code qui doivent composer avec ThreadAbortExceptions, voir @Mehrdad de répondre à Comment puis-je détecter un threadabortexception dans un bloc finally où il fait référence RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup Méthode et d'Exécution Limitées Régions


Le Rick Strahl l'article mentionné est instructif, et assurez-vous de lire les commentaires. Notez que Strahl la question était spécifique. Il voulait obtenir les données pour le client (une image) et ensuite le processus de hit-suivi de la base de données mise à jour qui n'a pas de ralentir la portion de l'image, qui s'est fait le problème de faire quelque chose après l'Intervention.La fin avait été appelé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X