क्या Response.End () हानिकारक माना जाता है?


198

यह KB आलेख कहता है कि ASP.NET Response.End()एक थ्रेड को रोकता है।

रिफ्लेक्टर से पता चलता है कि यह इस तरह दिखता है:

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

यह मुझे बहुत कठोर लगता है। जैसा कि KB लेख कहता है, निम्नलिखित एप्लिकेशन में किसी भी कोड को Response.End()निष्पादित नहीं किया जाएगा, और यह कम से कम विस्मय के सिद्धांत का उल्लंघन करता है। यह लगभग Application.Exit()एक WinForms ऐप की तरह है। थ्रेड Response.End()एबॉर्ट अपवाद अपवाद के कारण उपलब्ध नहीं है, इसलिए कोड में आस पास try... finallyसंतुष्ट नहीं करेगा।

यह मुझे आश्चर्यचकित करता है कि क्या मुझे हमेशा बचना चाहिए Response.End()

किसी को भी बता सकते हैं, जब मैं का उपयोग करना चाहिए Response.End(), जब Response.Close()और जब HttpContext.Current.ApplicationInstance.CompleteRequest()?

रेफरी: रिक स्ट्राल की ब्लॉग प्रविष्टि


मेरे द्वारा प्राप्त इनपुट के आधार पर, मेरा उत्तर है, हां, Response.Endहानिकारक है , लेकिन यह कुछ सीमित मामलों में उपयोगी है।

  • असाधारण स्थितियों में Response.End()तुरंत समाप्त करने के लिए, एक पहुंच से बाहर फेंकने के रूप में उपयोग करें HttpResponse। डिबगिंग के दौरान भी उपयोगी हो सकता है। नियमित प्रतिक्रियाओं को पूरा करने से बचेंResponse.End()
  • Response.Close()क्लाइंट के साथ कनेक्शन को तुरंत बंद करने के लिए उपयोग करें। प्रति इस MSDN ब्लॉग पोस्ट , इस विधि सामान्य HTTP अनुरोध प्रसंस्करण के लिए इरादा नहीं है। यह अत्यधिक संभावना नहीं है कि आपके पास इस पद्धति को कॉल करने का एक अच्छा कारण होगा।
  • CompleteRequest()एक सामान्य अनुरोध को समाप्त करने के लिए उपयोग करें। CompleteRequestASP.NET पाइपलाइन EndRequestघटना के आगे कूदने का कारण बनता है , वर्तमान HttpApplicationघटना के पूरा होने के बाद । इसलिए यदि आप कॉल करते हैं CompleteRequest, तो प्रतिक्रिया के लिए कुछ और लिखें, क्लाइंट को लिखित भेजा जाएगा।

संपादन - 13 अप्रैल 2011

आगे स्पष्टता यहाँ उपलब्ध है:
- MSDN ब्लॉग पर उपयोगी पोस्ट
- जॉन रीड द्वारा उपयोगी विश्लेषण


2
पता नहीं इस जवाब के बाद से क्या बदल गया है, लेकिन मैं Response.End ThreadAbortExceptionअभी ठीक कर रहा हूं ।
मसलो

1
मन भी है कि में भालू Response.Redirectऔर Server.Transferदोनों कॉल Response.Endऔर भी बचा जाना चाहिए।
ओवेन ब्लैकर

जवाबों:


66

यदि आपने अपने एप्लिकेशन पर अपवाद लकड़हारा नियोजित किया था, तो उसे ThreadAbortExceptionइन सौम्य Response.End()कॉल से एस के साथ पानी पिलाया जाएगा । मुझे लगता है कि यह Microsoft के "इसे बंद करो!" कहने का तरीका है।

मैं केवल तभी उपयोग करूंगा Response.End()जब कुछ असाधारण स्थिति होगी और कोई अन्य कार्रवाई संभव नहीं थी। हो सकता है कि तब, इस अपवाद को लॉग करना वास्तव में एक चेतावनी का संकेत दे सकता है।


107

टी एल; डॉ

प्रारंभ में मैंने सिफारिश की थी कि आपको अपनी सभी कॉल को [Response.End] के साथ [...] कम्प्लीट रीसरेस्ट () कॉल से बदलना चाहिए, लेकिन यदि आप पोस्टबैक प्रोसेसिंग और html रेंडरिंग से बचना चाहते हैं तो आपको जोड़ना पड़ेगा [..] ।] ओवरराइड भी करता है।

जॉन रीड , "अंतिम विश्लेषण"


प्रति MSDN, जॉन रीड , और एलेन रेनन:

ASP.NET प्रदर्शन - अपवाद प्रबंधन - अपवाद लिखने वाले कोड लिखें

Server.Transfer, Response.Redirect, Response.End तरीके सभी अपवादों को बढ़ाते हैं। इन तरीकों में से प्रत्येक आंतरिक रूप से Response.End कहते हैं। Response.End को कॉल, बदले में, एक ThreadAbortException अपवाद का कारण बनता है

ThreadAbortException समाधान

HttpApplication.CompleteRequest () एक वैरिएबल सेट करता है जो थ्रेड को HttpApplication इवेंट पाइपलाइन में अधिकांश घटनाओं को छोड़ने का कारण बनता है [-] पेज इवेंट चेन नहीं बल्कि एप्लिकेशन इवेंट चेन।

...

एक क्लास लेवल वैरिएबल बनाएं जो पेज को समाप्त कर दे और फिर आपके ईवेंट को प्रोसेस करने या आपके पेज को रेंडर करने से पहले वेरिएबल को चेक करे। [...] मैं सिर्फ RaisePostBackEvent और रेंडर तरीकों को ओवरराइड करने की सलाह दूंगा

Resp..End और Response.Close का उपयोग सामान्य अनुरोध प्रसंस्करण में नहीं किया जाता है जब प्रदर्शन महत्वपूर्ण होता है। प्रतिक्रिया। और एक संबंधित प्रदर्शन जुर्माना के साथ अनुरोध प्रसंस्करण को समाप्त करने का एक सुविधाजनक, भारी-भरकम साधन है। Response.Close IIS / सॉकेट स्तर पर HTTP प्रतिक्रिया की तत्काल समाप्ति के लिए है और KeepAlive जैसी चीजों के साथ मुद्दों का कारण बनता है।

ASP.NET अनुरोध को समाप्त करने की अनुशंसित विधि HttpApplication.CompleteRequest है। ध्यान रखें कि HttpApplication.CompleteRequest IIS / ASP.NET एप्लिकेशन पाइपलाइन के बाकी हिस्सों से ASP.NET रेंडरिंग को मैन्युअल रूप से छोड़ना होगा, ASP.NET पेज पाइपलाइन नहीं है (जो ऐप पाइपलाइन में एक चरण है)।


कोड

कॉपीराइट © 2001-2007, C6 सॉफ्टवेयर, इंक सबसे अच्छा मैं बता सकता था।


संदर्भ

HttpApplication.CompleteRequest

ASP.NET का कारण बनता है कि सभी घटनाओं को दरकिनार करें और निष्पादन की HTTP पाइपलाइन श्रृंखला में फ़िल्टरिंग करें और सीधे EndRequest घटना को निष्पादित करें।

Response.End

यह विधि केवल ASP- संगतता के लिए दी गई है, COM- आधारित वेब-प्रोग्रामिंग तकनीक के साथ संगतता के लिए है जो ASP.NET से पहले है। ASP.NET की व्याख्या की गई है। [महत्व दिया]

Response.Close

यह विधि क्लाइंट को अचानक तरीके से कनेक्शन समाप्त कर देती है और सामान्य HTTP अनुरोध प्रसंस्करण के लिए अभिप्रेत नहीं है । [महत्व दिया]


4
> ध्यान रखें कि HttpApplication.CompleteRequest IIS / ASP.NET एप्लिकेशन पाइपलाइन के बाकी हिस्सों से ASP.NET रेंडरिंग को मैन्युअल रूप से छोड़ना होगा। ASP.NET पेज पाइपलाइन नहीं है (जो ऐप पाइपलाइन में एक चरण है)। और आप इसे कैसे पूरा करते हैं?
पायलटबोट

1
उस कोड का लिंक देखें जहां जॉन रीड ने झंडा सेट करने का तरीका दिखाया और वांछित होने पर सामान्य कार्यान्वयन को छोड़ने के लिए पेज के RaisePostBackEvent और रेंडर तरीकों को ओवरराइड किया। (आप शायद बेस क्लास में ऐसा करेंगे जो आपके ऐप के सभी पेजों को इनहेरिट करना चाहिए।) web.archive.org/web/20101224113858/http://www.c6software.com/…
user423430

4
बस आराम करने के लिए: HttpApplication.CompleteRequest प्रतिक्रिया को समाप्त नहीं करता है जैसा कि Response.End करता है।
Glen Little

2
HttpApplication.CompleteRequest भी कोड प्रवाह को नहीं रोकता है, इसलिए बाद की लाइनें चालू रहती हैं। यह उस चीज़ को प्रभावित नहीं कर सकता है जो ब्राउज़र देखता है, लेकिन यदि वे लाइनें किसी अन्य प्रसंस्करण को करते हैं, तो यह वास्तव में भ्रमित हो सकता है।
जोशुआ फ्रैंक

3
मैं यह नहीं सोच सकता कि वेब फॉर्म डिजाइन से टूट गया है। प्रतिसाद को घटाना और प्रतिसाद देना अधिक है। मैं यह नहीं देख सकता कि कहां Response.End () "अधिक" यहां हानिकारक है। इसके अलावा, माइक्रोसॉफ्ट व्यवहार करता है `इस कोड से एक सामान्य स्पष्ट रूप घटना के रूप में ThreadAbortedException ': referencesource.microsoft.com/#System.Web/UI/Page.cs,4875 Response.End (के खिलाफ है कि एक बात है) है कि यह असफल हो सकता है है प्रतिक्रिया को निरस्त करना, जिसके परिणामस्वरूप प्रतिक्रिया कभी-कभी प्रदर्शित हो सकती है।
घसान

99

यह प्रश्न प्रतिक्रिया के बारे में जानकारी के लिए सभी Google खोजों में सबसे ऊपर दिखाई देता है। इस तरह से अन्य खोजों के लिए खुद को, जो पूरे ASPX पृष्ठ को रेंडर किए बिना किसी घटना के जवाब में CSV / XML / PDF आदि पोस्ट करना चाहते हैं, यह है कि मैं इसे कैसे करता हूं । (इस तरह के एक सरल कार्य 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()

1
ऐसा करने के लिए आपको APSX पृष्ठ का उपयोग नहीं करना चाहिए। यह बहुत व्यर्थ प्रयास है। आप एक ASMX या वेब सेवा, कुछ भी लेकिन एक ASPX पृष्ठ का उपयोग करने वाले हैं।
मैटमनर

19
यह सबसे आसान कार्यान्वयन के साथ उत्तर लगता है। कुंजी Response.SuppressContent = True है।
क्रिस वेबर

3
@ मट्टमनसर - एक ही संसाधन के विभिन्न प्रतिनिधित्व के लिए एक अलग पृष्ठ रखना हमेशा आसान / सर्वोत्तम / उचित नहीं होता है। REST के बारे में सोचें, आदि यदि ग्राहक इंगित करता है कि वे सीएसवी चाहते हैं, तो हेडर या परम के माध्यम से xml, यह विधि निश्चित रूप से सबसे अच्छी होगी, जबकि अभी भी asp.net की सामान्य रेंडरिंग सुविधाओं के माध्यम से HTML समर्थन प्रदान करता है।
क्रिस वेबर

1
यह मेरे लिए काम नहीं किया। मेरे पास एक पेज था जो Response.End () के साथ काम करता था, लेकिन Response.Close (), Response.Flush () के सभी प्रकार के संयोजनों का उपयोग करता था। HttpContext.Current.ApplicationInstance.CompleteRequest () और विभिन्न अन्य चीजें काम नहीं करती अगर मेरे पास प्रतिक्रिया पर GzipStream फ़िल्टर होता। जो दिखाई दे रहा था वह यह था कि पेज अभी भी मेरी फ़ाइल के साथ आउटपुट हो रहा था। मैं अंत में रेंडर () फ़ंक्शन (खाली होने के लिए) को ओवररोड करता हूं और इसने मेरे लिए इसे हल किया।
एरिक

1
एप्लिकेशन पाइपलाइन के पूर्ण रूप से कटे हुए भाग, लेकिन फिर भी पेज रेंडरिंग प्रक्रिया के शेष भाग के माध्यम से चलेंगे, यह प्रतिक्रिया की तरह तत्काल रोक नहीं है। इस पृष्ठ पर अन्य उत्तरों में गहराई से स्पष्टीकरण दिए गए हैं।
Jay Zelos

11

"मैं अभी भी Response.Close और FullRequest ()" के बीच अंतर नहीं जानता के सवाल पर मैं कहूंगा:

पूरी तरह से पसंद करते हैं (), Response.Close () का उपयोग न करें।

इस मामले का एक अच्छा किया सारांश के लिए निम्नलिखित लेख देखें ।

ध्यान रहे कि कंप्लीट्रेसेस्ट () कॉल करने के बाद भी कुछ टेक्स्ट (जैसे ASPX कोड से रिडंडर्ड) को रिस्पॉन्स आउटपुट स्ट्रीम में जोड़ा जाएगा। आप निम्न लेख में वर्णित के रूप में रेंडर और RaisePostBackEvent तरीकों को ओवरराइड करके इसे रोक सकते हैं ।

BTW: मैं Response.End () का उपयोग करने से रोकने के साथ सहमत हूं, खासकर जब फ़ाइल डाउनलोड का अनुकरण करने के लिए http स्ट्रीम में डेटा लिखते हैं। हमने तब तक Response.End () का उपयोग किया है जब तक कि हमारी लॉग फ़ाइल ThreadAbortException से भरी नहीं हो जाती।


जैसा कि आप वर्णन करते हैं, मैं रेंडर को ओवरराइड करने में दिलचस्पी रखता हूं, लेकिन "निम्नलिखित लेख" का लिंक मर चुका है। शायद आप अपनी प्रविष्टि को अपडेट कर सकते हैं?
पक्ओगोमेज़

देर से जवाब के लिए क्षमा करें। मुझे ठीक से याद नहीं, उस लेख में क्या था। हालाँकि, मैंने इसे webarchive.org: web.archive.org/web/20101224113858/http://www.c6software.com/…
Jan olaotola

9

मैं " Response.End हानिकारक है " कथन से असहमत हूं । यह निश्चित रूप से हानिकारक नहीं है। प्रतिक्रिया। और यह क्या कहता है; यह पृष्ठ का निष्पादन समाप्त करता है। रिफ्लेक्टर का उपयोग यह देखने के लिए कि इसे कैसे लागू किया गया था, इसे केवल शिक्षाप्रद के रूप में देखा जाना चाहिए।


मेरे 2cent सिफारिश
से बचने का उपयोग कर Response.End()नियंत्रण प्रवाह के रूप में।
डीओ उपयोग Response.End()आप अनुरोध निष्पादन बंद करो और पता है कि (आमतौर पर) * कोई कोड उस बिंदु अतीत निष्पादित करेंगे होने की जरूरत है।


* Response.End()और थ्रेडएबोर्टेसेप्शन एस।

Response.End() यह वर्तमान कार्यान्वयन के रूप में (ओपी द्वारा उल्लेख किया गया है) के एक भाग के रूप में एक थ्रेडबॉस्ट अपवाद फेंकता है।

ThreadAbortException एक विशेष अपवाद है जिसे पकड़ा जा सकता है, लेकिन यह स्वचालित रूप से फिर से पकड़ ब्लॉक के अंत में उठाया जाएगा।

यह देखने के लिए कि कोड को कैसे लिखना है जो थ्रेडबोर्ट एक्ससेप्शन से निपटना चाहिए, तो @ मेहरदाद का एसओ को जवाब देखें मैं आखिरकार थ्रेडबोर्टेक्ससेप्शन का पता कैसे लगा सकता हूं जहां वह RuntimeHelpers.ExecuteCithWithGuaranteedCleanup विधि और विवश निष्पादन क्षेत्र का संदर्भ देता है।


रिक Strahl लेख में उल्लेख किया है शिक्षाप्रद है, और साथ ही टिप्पणी पढ़ने के लिए सुनिश्चित करें। ध्यान दें कि स्ट्राहल का मुद्दा विशिष्ट था। वह क्लाइंट (एक छवि) को डेटा प्राप्त करना चाहता था और फिर हिट-ट्रैकिंग डेटाबेस अपडेट को संसाधित करता था जो छवि की सेवा को धीमा नहीं करता था, जिसने प्रतिक्रिया के बाद कुछ करने की अपनी समस्या बना दी थी। और उसे बुलाया गया था।


हमने इस पोस्ट को देखा stackoverflow.com/questions/16731745/… Response.SuppressContent = True HttpContext.Current.ApplicationInstance.CompleteRequest () के बजाय Response.End ()
jazzBox

3

मैंने प्रोग्राम प्रवाह को नियंत्रित करने के लिए Response.End () का उपयोग करने पर कभी विचार नहीं किया है।

हालाँकि, Response.End () उपयोगकर्ता के लिए फ़ाइलों की सेवा करते समय उदाहरण के लिए उपयोगी हो सकता है।

आपने प्रतिक्रिया के लिए फ़ाइल लिखी है और आप नहीं चाहते कि प्रतिक्रिया में कुछ और जोड़ा जाए क्योंकि यह आपकी फ़ाइल को दूषित कर सकता है।


1
मैं "प्रतिक्रिया पूर्ण है" कहने के लिए एक एपीआई की आवश्यकता को समझता हूं। लेकिन Response.End () भी थ्रेड एबॉर्ट करता है। यह सवाल का क्रूस है। उन दो चीजों को युगल करना कब एक अच्छा विचार है?
चेसो

2

मैंने .NET और क्लासिक ASP दोनों में Response.End () का उपयोग किया है और इससे पहले कि वह जबरदस्ती चीजों को समाप्त कर दे। उदाहरण के लिए, मैं इसका उपयोग तब करता हूं जब लॉगिन प्रयासों की एक प्रमाणित राशि होती है। या जब किसी सुरक्षित पृष्ठ को अनअथेंटेड लॉगिन (मोटे उदाहरण) से प्राप्त किया जा रहा हो:

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

जब मैं एक फ्लश का उपयोग करूँगा एक उपयोगकर्ता के लिए फ़ाइलों की सेवा, अंत मुद्दों का कारण बन सकता है।


ध्यान रखें, फ्लश () "यह अंत है" नहीं है। यह सिर्फ "अब तक सब कुछ फ्लश है।" आप "यह अंत है" चाहते हैं, इसका कारण यह हो सकता है कि ग्राहक को यह बता दें कि इसमें सभी सामग्री है, जबकि सर्वर जा सकता है और अन्य काम कर सकता है - लॉग फाइल को अपडेट कर सकता है, डेटाबेस काउंटर को क्वेरी कर सकता है, या जो भी हो। यदि आप Response.Flush को कॉल करते हैं और फिर उन चीजों में से एक करते हैं, तो ग्राहक अधिक इंतजार करना जारी रख सकता है। यदि आप Response.End () कहते हैं, तो नियंत्रण कूदता है और DB को प्रश्न नहीं मिलते हैं, आदि
चीज़ो

आप वैकल्पिक रूप से ओवरराइड रेस्पोंस का उपयोग कर सकते हैं। रीडायरेक्ट ("....", सत्य) जहां बूल 'एंडरस्पॉन्स है: यह बताता है कि क्या पेज का वर्तमान निष्पादन समाप्त होना चाहिए "
रॉबर्ट पॉलसन

लॉग क्रेडेंशियल्स द्वारा सुरक्षित किए जाने वाले पृष्ठों की सुरक्षा के लिए फ़ॉर्म ऑथेंटिकेशन फ्रेमवर्क का उपयोग करना हमेशा बेहतर होता है।
रॉबर्ट पॉलसन 3

3
वास्तव में, अपने आप को सही करने के लिए, मेरा मानना ​​है कि Response.Redirect और Server.Transfer का डिफ़ॉल्ट रिस्पांस कॉल करना है। और आंतरिक रूप से तब तक जब तक आप ओवरराइड को कॉल न करें और 'झूठे' पास न करें। जिस तरह से आपके कोड को Response.End लिखा जाता है उसे कभी नहीं कहा जाता है। ,
रॉबर्ट पॉलसन

1
Response.end क्लासिक एएसपी की तुलना में .net में बहुत अलग तरीके से काम करता है। .Net में यह थ्रेडबोर्टेक्ससेप्शन का कारण बनता है, जो कि बहुत बुरा हो सकता है।
एंडी

2

मैंने केवल Response.End () को परीक्षण / डिबगिंग तंत्र के रूप में उपयोग किया है

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

अनुसंधान के संदर्भ में आपने जो कुछ भी पोस्ट किया है, उसे देखते हुए, मैं कहूंगा कि यदि यह प्रतिक्रिया की आवश्यकता है तो यह एक बुरा डिजाइन होगा


0

क्लासिक एस्प पर, मेरे पास कुछ अजाक्स कॉल पर 3 से 10 सेकंड तक TTFB (टाइम टू फर्स्ट बाइट) था, कई और SQL कॉल के साथ नियमित पेजों पर TTFB से बहुत बड़ा।

पेज में इंजेक्ट किया गया ajax HTML का एक सेगमेंट था।

TTFB रेंडर समय से कई सेकंड लंबा था।

अगर मैंने रेंडर के बाद response.end जोड़ा, तो TTFB बहुत कम हो गया।

मैं एक "</ body> </ html>" का उत्सर्जन करके एक ही प्रभाव प्राप्त कर सकता था, लेकिन यह संभवत: जब json या xml आउटपुट नहीं करता है; यहाँ response.end की जरूरत है।


मुझे पता है कि यह एक पुराना उत्तर है, लेकिन फिर से, क्लासिक एस्प पुराना है। मुझे यह उपयोगी लगा ;-)
लीफ़ नलैंड्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.