क्यों प्रतिक्रिया। अप्रत्यक्ष कारण System.Threading.ThreadAbortException?


230

जब मैं रिस्पांस का उपयोग करता हूं। रीडायरेक्ट (...) अपने फॉर्म को एक नए पृष्ठ पर पुनर्निर्देशित करने के लिए मुझे त्रुटि मिलती है:

Mscorlib.dll में 'System.Threading.ThreadAbortException' प्रकार का पहला मौका अपवाद 'System.Threading.ThreadAbortException'
प्रकार का अपवाद mscorlib.dll में हुआ, लेकिन उपयोगकर्ता कोड में संभाला नहीं गया

इस बारे में मेरी समझ यह है कि वेबसर्वर द्वारा शेष पेज को रिस्पॉन्स करने के कारण त्रुटि हो रही है।

मुझे पता है कि मैं एक दूसरा पैरामीटर जोड़ सकता हूं Response.Redirectजिसे एंडरस्पॉन्स कहा जाता है। अगर मैं एंडरसन को ट्रू में सेट करता हूं तो मुझे फिर भी त्रुटि मिलती है लेकिन अगर मैं इसे गलत पर सेट करता हूं तो मैं नहीं करता। मुझे पूरा यकीन है कि हालांकि इसका मतलब है कि वेबसर्वर बाकी पेज को चला रहा है, जिनसे मैं पुनर्निर्देशित हूं। जो कम से कम कहने में अक्षम प्रतीत होगा। क्या ऐसा करने के लिए इससे अच्छा तरीका है? Response.Redirectपुराने पृष्ठ को लोड करने से रोकने के लिए कोई अन्य तरीका है या नहीं, जहां मुझे ए नहीं मिलेगा ThreadAbortException?

जवाबों:


332

सही पैटर्न Redirect overload को endResponse = false से कॉल करना है और IIS पाइपलाइन को यह बताने के लिए कॉल करना है कि नियंत्रण वापस करने के बाद यह EndRequest स्टेज पर सीधे आगे बढ़ना चाहिए:

Response.Redirect(url, false);
Context.ApplicationInstance.CompleteRequest();

थॉमस मार्क्वर्ट का यह ब्लॉग पोस्ट अतिरिक्त विवरण प्रदान करता है, जिसमें एक Application_Erive हैंडलर के अंदर पुनर्निर्देशन के विशेष मामले को कैसे संभालना है।


6
इसके बाद कोड निष्पादित करता है Context.ApplicationInstance.CompleteRequest();। क्यों? क्या मुझे returnसशर्त रूप से इवेंट हैंडलर से लेना होगा?
इस्माइल

4
@ ईमेल: किसी भी बाद के कोड के निष्पादन को रोकने के लिए Redirect का पुराना संस्करण एक ThreadAbortException फेंकता है। नया, पसंदीदा संस्करण फेंकता नहीं है, लेकिन यदि आप हैंडलर में अतिरिक्त कोड रखते हैं, तो आप जल्दी नियंत्रण वापस करने के लिए जिम्मेदार हैं।
जोएल फिलमोर

12
मुझे लगता है कि The old version of Redirectआपकी टिप्पणी में आपके द्वारा उपयोग किए जाने वाले वाक्यांश के बजाय "दूसरा अधिभार" कहना अधिक सटीक है , यह ऐसा नहीं है कि एमएस ने कार्यान्वयन को बदल दिया है, यह सिर्फ एक और अधिभार है।
बॉर्नटोड कोड

2
मुझे नहीं लगता कि यह एक आदर्श पैटर्न है। आप पृष्ठ को प्रतिक्रिया समाप्त नहीं करने और निष्पादन जारी रखने और फिर अनुरोध को प्रोग्रामिक रूप से पूरा करने के लिए कह रहे हैं। लेकिन aspx पृष्ठ और घटना संचालकों के प्रतिपादन के बारे में क्या? प्रतिक्रिया का अर्थ समाप्त नहीं होता है, यह "पूर्णरूपेण ()" मारने से पहले aspx पृष्ठ को प्रस्तुत करना समाप्त कर देगा। अब अगर मैं अपने पेज में एक सर्वर साइड प्रॉपर्टी का उपयोग कर रहा हूं तो मान्य लॉगिन निर्धारित करने के लिए एक सत्र चर कहा जाता है, जो यदि समाप्त हो जाता है, तो अनुप्रेषित करने से पहले एक शून्य अपवाद भी फेंक देगा। और इसे ठीक करने का एकमात्र तरीका यह है कि एंडरसेप्‍सन को सही बनाया जाए।
पेट

1
इस उत्तर को वोट करने जा रहा था, लेकिन उस पेज कोड को जारी रखा गया। यह मेरे मामले में आदर्श नहीं है। "ThreadAbortException" को संभालने या अनदेखा करने के लिए बहुत अधिक क्लीनर
DaniDev

159

ASP.Net WebForms में समस्या का कोई सरल और सुरुचिपूर्ण समाधान नहीं है Redirect। आप गंदे समाधान और थकाऊ समाधान के बीच चयन कर सकते हैं

गंदा : Response.Redirect(url)ब्राउज़र में एक रीडायरेक्ट भेजता है, और फिर ThreadAbortedExceptionवर्तमान थ्रेड को समाप्त करने के लिए ए फेंकता है । इसलिए किसी भी कोड को रीडायरेक्ट () कॉल से पहले निष्पादित नहीं किया जाता है। डाउनसाइड्स: यह बुरा अभ्यास है और इस तरह से धागे को मारने के लिए प्रदर्शन निहितार्थ हैं। इसके अलावा, ThreadAbortedExceptionsअपवाद लॉगिंग में दिखाई देगा।

थकाऊ : अनुशंसित तरीका कॉल करना है Response.Redirect(url, false)और फिर Context.ApplicationInstance.CompleteRequest(), कोड निष्पादन जारी रहेगा और पृष्ठ जीवनचक्र में बाकी इवेंट हैंडलर अभी भी निष्पादित किए जाएंगे। (जैसे यदि आप Page_Load में रीडायरेक्ट करते हैं, तो न केवल शेष हैंडलर निष्पादित किया जाएगा, Page_PreRender और इसी तरह अभी भी कॉल किया जाएगा - रेंडर किए गए पृष्ठ को केवल ब्राउज़र पर नहीं भेजा जाएगा। आप अतिरिक्त प्रसंस्करण से बच सकते हैं। उदाहरण के लिए, पृष्ठ पर एक ध्वज स्थापित करना, और उसके बाद किसी भी प्रक्रिया को करने से पहले बाद के घटना संचालकों को इस ध्वज की जाँच करने दें।

(दस्तावेज़ीकरण में CompleteRequestकहा गया है कि यह " HTTP.NET का कारण बनता हैसभी घटनाओं को दरकिनार करना और निष्पादन की HTTP पाइपलाइन श्रृंखला में फ़िल्टर करना "। इसे आसानी से गलत समझा जा सकता है। यह आगे HTTP फ़िल्टर और मॉड्यूल को बायपास करता है, लेकिन यह आगे की घटनाओं को बायपास नहीं करता है। वर्तमान पृष्ठ के जीवनचक्र में।)

गहरी समस्या यह है कि WebForms में अमूर्तता का स्तर कम होता है। जब आप ईवेंट हैंडलर में होते हैं, तो आप पहले से ही आउटपुट के लिए एक पेज बनाने की प्रक्रिया में होते हैं। किसी ईवेंट हैंडलर में रीडायरेक्ट करना बदसूरत है क्योंकि आप एक अलग पेज बनाने के लिए आंशिक रूप से उत्पन्न पेज को समाप्त कर रहे हैं। MVC के पास यह समस्या नहीं है क्योंकि नियंत्रण प्रवाह रेंडरिंग दृश्यों से अलग है, इसलिए आप RedirectActionनियंत्रक में केवल एक रिटर्न देकर , एक दृश्य उत्पन्न किए बिना एक साफ पुनर्निर्देशित कर सकते हैं ।


7
मेरा मानना ​​है कि मैंने अब तक सुने गए वेबफॉर्म का सबसे अच्छा विवरण "झूठ की चटनी" था।
22 अक्टूबर को mcfea

9
मुझे इस उत्तर में विस्तार की मात्रा पसंद है। स्वीकृत उत्तर की तुलना में बेहतर है
जेस

यदि आप गंदे विकल्प का उपयोग करते हैं , तो आप Visual Studio में ThreadAbortException पर ब्रेक को बंद कर सकते हैं। डीबग> अपवाद ...CLR> System.Threading> Uncheck System.Thread.ThreadAbortException का विस्तार करें
जेस

भगवान का शुक्र है कि हमारे पास उचित उत्तर वाला कोई व्यक्ति है, और यह सर्वोच्च मतदान वाला उत्तर होना चाहिए।
ABS

1
मेरे मामले में यह अपवाद प्रत्येक और हर बार के लिए नहीं आ रहा है, केवल बीच में कुछ समय के लिए यह घट रहा है। इसका अर्थ है कि यदि लाइव एप्लिकेशन के एक ही बटन पर क्लिक करना और यह काम कर रहा है, लेकिन जब उसी लिंक और उसी बटन को अन्य मशीन से क्लिक किया जाता है तो वह System.Threading.ThreadAbortException दे रहा है। किसी भी विचार क्यों यह हर बार नहीं हो रहा है ??
सागर शिर्के

33

मैं जानता हूँ कि मुझे देर हो रही है, लेकिन मैं ही कभी इस त्रुटि मिला है अगर मेरे Response.Redirectएक में है Try...Catchब्लॉक।

एक रिस्पांस कभी भी मत डालो। अप्रत्यक्ष एक कोशिश में ... पकड़ो ब्लॉक। यह बुरा अभ्यास है

संपादित करें

@ Kiquenet की टिप्पणी के जवाब में, यहां मैं Response.Redirect को Try ... Catch block में डालने के विकल्प के रूप में क्या करूँगा।

मैं दो चरणों में विधि / कार्य को तोड़ दूंगा।

कोशिश के अंदर एक कदम ... पकड़ो ब्लॉक अनुरोधित कार्यों को करता है और कार्यों की सफलता या विफलता को इंगित करने के लिए "परिणाम" मान सेट करता है।

प्रयास के बाहर चरण दो ... पकड़ो ब्लॉक पुनर्निर्देशित करता है (या नहीं) "परिणाम" मान के आधार पर।

यह कोड एकदम सही है और शायद इसकी नकल नहीं की जानी चाहिए क्योंकि मैंने इसका परीक्षण नहीं किया है

public void btnLogin_Click(UserLoginViewModel model)
{
    bool ValidLogin = false; // this is our "result value"
    try
    {
        using (Context Db = new Context)
        {
            User User = new User();

            if (String.IsNullOrEmpty(model.EmailAddress))
                ValidLogin = false; // no email address was entered
            else
                User = Db.FirstOrDefault(x => x.EmailAddress == model.EmailAddress);

            if (User != null && User.PasswordHash == Hashing.CreateHash(model.Password))
                ValidLogin = true; // login succeeded
        }
    }
    catch (Exception ex)
    {
        throw ex; // something went wrong so throw an error
    }

    if (ValidLogin)
    {
        GenerateCookie(User);
        Response.Redirect("~/Members/Default.aspx");
    }
    else
    {
        // do something to indicate that the login failed.
    }
}

@Kiquenet कृपया मेरे अद्यतन उत्तर को देखें कि मैं क्या करूँगा। इसका सबसे अच्छा कोर्स कहने के लिए नहीं, लेकिन मुझे लगता है कि यह एक व्यवहार्य विकल्प है।
ओरतुंड

जब तक मैंने कोशिश में अपना कोड नहीं लपेट लिया, तब तक यह समस्या नहीं थी ... मुझे आश्चर्य है कि अन्य कोड कॉल ने .NET में इस व्यवहार का कारण क्या है
दिलचस्प-नाम-यहाँ

8

Response.Redirect() वर्तमान अनुरोध को निरस्त करने के लिए एक अपवाद फेंकता है।

यह KB आलेख इस व्यवहार ( Request.End()और के लिए भी) का वर्णन करता हैServer.Transfer() विधियों के लिए) का ।

Response.Redirect()वहाँ के लिए एक अधिभार मौजूद है:

Response.Redirect(String url, bool endResponse)

अगर आप एंडरसन पास करते हैं तो गलत है , तो अपवाद नहीं फेंका गया है (लेकिन रनटाइम चालू अनुरोध को संसाधित करना जारी रखेगा)।

यदि एंडरस्पॉन्स = सही (या यदि अन्य अधिभार का उपयोग किया जाता है), तो अपवाद को फेंक दिया जाता है और वर्तमान अनुरोध तुरंत समाप्त हो जाएगा।


7

यहां समस्या पर आधिकारिक लाइन है (मैं नवीनतम नहीं ढूंढ सका, लेकिन मुझे नहीं लगता कि बाद के संस्करणों के लिए स्थिति बदल गई है।)


5
लिंक के बावजूद @svick लिंक, केवल उत्तर वास्तव में महान जवाब नहीं हैं। meta.stackexchange.com/q/8231 I think that links are fantastic, but they should never be the only piece of information in your answer.
रायन गेट्स

7

यह सिर्फ Response.Redirect(url, true) काम करता है। यह फेंकता हैThreadAbortException थ्रेड को निरस्त करने लिए । बस उस अपवाद को अनदेखा करें। (मुझे लगता है कि यह कुछ वैश्विक त्रुटि हैंडलर / लकड़हारा है जहाँ आप इसे देखते हैं?)

एक दिलचस्प संबंधित चर्चा है Response.End()हानिकारक माना?


4
प्रतिक्रिया के समयपूर्व अंत से निपटने के लिए एक थ्रेड को नष्ट करना वास्तव में भारी हाथ की तरह लगता है। मुझे यह अजीब लगता है कि यह फ्रेम अपनी जगह लेने के लिए एक नए कताई के बजाय धागे का फिर से उपयोग करना पसंद नहीं करेगा।
खर्चा

3

इसके अलावा मैं अन्य समाधान की कोशिश की, लेकिन कोड के कुछ अनुप्रेषित के बाद निष्पादित।

public static void ResponseRedirect(HttpResponse iResponse, string iUrl)
    {
        ResponseRedirect(iResponse, iUrl, HttpContext.Current);
    }

    public static void ResponseRedirect(HttpResponse iResponse, string iUrl, HttpContext iContext)
    {
        iResponse.Redirect(iUrl, false);

        iContext.ApplicationInstance.CompleteRequest();

        iResponse.BufferOutput = true;
        iResponse.Flush();
        iResponse.Close();
    }

इसलिए यदि रीडायरेक्ट के बाद कोड निष्पादन को रोकने की आवश्यकता है

try
{
   //other code
   Response.Redirect("")
  // code not to be executed
}
catch(ThreadAbortException){}//do there id nothing here
catch(Exception ex)
{
  //Logging
}

1
सिर्फ जोर्ज जवाब द्वारा अनुवर्ती। यह हमेशा थ्रेड एबॉर्ट अपवाद के लॉगिंग को हटा देगा।
मैक्सिम लावरोव

जब कोई पूछता है कि उसे एक अपवाद क्यों मिलता है, तो उसे सिर्फ कोशिश के साथ खेलने के लिए कहा जाता है..कैच का जवाब नहीं है। स्वीकृत उत्तर देखें। मैं आपके उत्तर पर टिप्पणी करते हुए "देर जवाब" की समीक्षा
manuell

इसका रिस्पांस के दूसरे तर्क के लिए गलत प्रभाव डालने के समान ही है। रीडायरेक्ट, लेकिन थ्रेडअबॉर्टीसेप्शन को कैप्चर करने की तुलना में "झूठा" एक अच्छा समाधान है। मुझे नहीं लगता कि इस तरह से ऐसा करने का कोई अच्छा कारण है।
NickG

2

मैं भी इसे से बचने की कोशिश की, बस मामले में थ्रेड पर मैन्युअल रूप से कर रहा है, लेकिन मैं इसे "कंप्लीट्रेसेस्टेस्ट" के साथ छोड़ देता हूं और आगे बढ़ता हूं - मेरे कोड में वैसे भी पुनर्निर्देशन के बाद कमांड वापस आ गई है। तो यह किया जा सकता है

public static void Redirect(string VPathRedirect, global::System.Web.UI.Page Sender)
{
    Sender.Response.Redirect(VPathRedirect, false);
    global::System.Web.UI.HttpContext.Current.ApplicationInstance.CompleteRequest();
}

1

मैं जो करता हूं, वह इस अपवाद को पकड़ता है, साथ में एक और संभावित अपवाद। आशा है कि यह किसी की मदद करेंगे।

 catch (ThreadAbortException ex1)
 {
    writeToLog(ex1.Message);
 }
 catch(Exception ex)
 {
     writeToLog(ex.Message);
 }

2
बेहतर से बचने के ThreadAbortException अपवाद से पकड़ और कुछ भी नहीं ?
किकेनेट

-1

मुझे वह समस्या भी थी।

के Server.Transferबजाय का उपयोग करने का प्रयास करेंResponse.Redirect

मेरे लिए काम किया।


2
Server.Transfer अभी भी एक ThreadAbortException को फेंकना चाहिए: support.microsoft.com/kb/312629 , इसलिए यह अनुशंसित समाधान नहीं है।
जोएल बेकहम

9
Server.Transfer उपयोगकर्ता को रीडायरेक्ट नहीं भेजेगा। यह पूरी तरह से एक अलग उद्देश्य है!
मार्सेल

1
Server.transfer और responce.redirect अलग-अलग हैं
mzonerz
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.