2009-04-09 9 views
12

उपयोगकर्ता पेज spawn.aspx जो फिर एक आधे दर्जन धागे spawns, पृष्ठों प्रतिपादन सभीका उपयोग करते हुए एक HttpContext धागे भर में

((System.Web.IHttpHandler)instance).ProcessRequest(reference to spawn's HTTPContext); 

का उपयोग कर तथ्य यह है कि ASP.Net प्रतीत होता है उपयोगकर्ता भेज रहा है के बारे में चिंता मत करो हिट 1 अनुरोध के लिए 7 प्रतिक्रियाएं, उस भाग को संभाला जाता है और केवल एक प्रतिक्रिया भेजी जाती है।

System.IndexOutOfRangeException 
at System.collections.ArrayList.Add 
at System.Web.ResponseDependencyList.AddDependencies(String[] items, String argname, Boolean cloneArray, DateTime utcDepTime) 
at System.Web.ResponseDependencyList.AddDependencies(String[] items, String argname, Boolean cloneArray, String requestVritualPath) 
at System.Web.UI.Page.AddWrappedFileDependencies(Object virtualFileDependencies) 
at ASP.spawned_page_no_1_aspx.FrameworkInitialize() 
at System.Web.UI.Page.ProcessRequest 

हम इसे कहीं और नकल नहीं कर सकते हैं:

समस्या है, एक उच्च यातायात पर्यावरण (हमारी उत्पादन पर्यावरण) कई धागे (क्वाड-quads) के साथ में हम कोई त्रुटि मिलती है। मेरा सहकर्मी मानता है कि ऐसा इसलिए है क्योंकि मैं मूल HTTPContext का पुन: उपयोग कर रहा हूं और इसे अन्य धागे में गुजर रहा हूं, और यह थ्रेड-सेफ नहीं है।

इस तर्क के बाद, मैंने धागे में जाने के लिए एक नया HTTPContext बनाने का प्रयास किया है। लेकिन इसके कुछ हिस्सों में "गठबंधन" नहीं होगा। विशेष रूप से, मुझे सत्र ऑब्जेक्ट को नए HTTPContext में प्राप्त करने की आवश्यकता है। मुझे कल्पना है कि मैं कैश की तरह, अन्य भागों को भी प्राप्त करना चाहता हूं। रिकॉर्ड HTTPContext.Current.Session.IsSynchronized के लिए गलत है।

मेरे प्रश्न हैं:

  1. क्या आपको लगता है त्रुटि धागे भर में HttpContext का उपयोग करने से है?
  2. मैं इसे कैसे ठीक कर सकता हूं?
  3. यदि फिक्स प्रत्येक थ्रेड के लिए HTTPContext को डुप्लिकेट कर रहा है, तो मैं सत्र (और कैश) को नए में कैसे प्राप्त कर सकता हूं? अनुरोध और प्रतिक्रिया सीटीआर में आती है, लेकिन सत्र सेटटेबल नहीं है।

संपादित करें: अधिक जानकारी

तो वापस इस बयान के लिए जा रहा: "तथ्य यह है कि ASP.Net प्रतीत होता है 1 अनुरोध के लिए उपयोगकर्ता भेज रहा है 7 प्रतिक्रियाओं के बारे में चिंता मत करो, वह हिस्सा नियंत्रित किया जाता है और केवल एक प्रतिक्रिया भेजी जाती है। " रेमंड चेन के विशाल प्रशंसक, मैं आपसे सहमत हूं: "अब आपके पास दो समस्याएं हैं" किसी और जानकारी की अनुपस्थिति में एक उचित बयान है।

वास्तव में क्या हो रहा है कि मैं वापस भेजने के लिए एक एक्सेल दस्तावेज़ बना रहा हूं। Spawn.aspx पृष्ठ में यह कुछ राज्य जानकारी स्थापित कर रहा है, जिसमें तथ्य यह है कि यह एक्सेल करने के लिए प्रतिपादन कर रहा है, और ऑब्जेक्ट को प्रतिपादन करने के लिए। प्रत्येक स्पॉन्टेड पेज उस जानकारी को प्राप्त करता है, और जब तक ऑब्जेक्ट को प्रस्तुत करने की बारी न हो जाए तब तक अवरुद्ध हो जाएगा। सचमुच इस तरह दिखाई देता है:

protected override void Render(System.Web.UI.HtmlTextWriter writer) 
{ 
    if (this.RenderToExcel) 
    { 
     Deadlocker.SpinUntilCurrent(DeadLockToken); 
     RenderReport(this, this.XLSWriter); 
     Deadlocker.Remove(DeadLockToken); 
    } 
    else 
     base.Render(writer); 
} 

लेकिन ऊपर है कि बात करने के लिए सभी संसाधन - डेटाबेस का उपयोग, नियंत्रण पदानुक्रम, सभी कि समानांतर में किया है। और इसमें बहुत कुछ है - पर्याप्त है कि इसे रेंडर पर अवरुद्ध करने के दौरान इसे फिर से खराब करने से कुल मिलाकर आधे से अधिक समय में कटौती होगी।

और इसका सबसे अच्छा हिस्सा यह है कि एक्सेल रेंडर के लिए कुछ भी लिखना नहीं था। सभी नियंत्रणों को पता है कि कैसे उत्कृष्टता प्राप्त करने के लिए खुद को प्रस्तुत करना है, और आप स्वतंत्र रूप से प्रत्येक स्पैन किए गए पृष्ठ पर जा सकते हैं (वास्तव में यह 'सामान्य मामला' है - एक्सेल रिपोर्ट केवल सभी तैयार पृष्ठों का एकत्रीकरण है।)

तो मैंने सोचा अंतिम परिणाम "आप ऐसा नहीं कर सकते हैं, आपको दृष्टिकोण पर पुनर्विचार करने की आवश्यकता है" - लेकिन मुझे कम से कम प्रयास करना पड़ा, क्योंकि तथ्य यह है कि सबकुछ किसी भी तर्क या किसी भी कोड को डुप्लिकेट किए बिना या कुछ भी अमूर्त किए बिना इतना अच्छी तरह से काम करता है बस इतना सही है। और यह केवल बहु-थ्रेडिंग है जो समस्या है, अगर मैं पृष्ठों को क्रमशः प्रस्तुत करता हूं तो सब कुछ ठीक है, बस धीमा।

उत्तर

2

आपके सहकर्मी सही हैं, अगर एक धागा संसाधन को लॉक करता है और दूसरा थ्रेड इसका उपयोग करने का प्रयास करता है तो आपका थ्रेड पूल उछाल जाता है! बहुत अच्छा परिणाम नहीं है। अधिकांश लोग नई वस्तुओं को बनाकर और उन्हें पैरामीटरयुक्त धागे में गुजरकर इसे हल करते हैं। यदि आपको बिल्कुल उसी ऑब्जेक्ट का उपयोग करने की आवश्यकता है तो आपको कुछ कोड लागू करना होगा जो पहले यह देखने के लिए जांच करता है कि संसाधन किसी अन्य थ्रेड द्वारा उपयोग किया जा रहा है और फिर फिर से जांचने से पहले थोड़ी देर प्रतीक्षा करता है। एक उदाहरण है कि एक IsInUse बूल बनाने के लिए जो आप हमेशा पहले जांचते हैं, तो आपका थ्रेड इसे सत्य पर सेट करता है यदि वह उस संसाधन का उपयोग कर रहा है, तो जब यह किया जाता है तो गलत होता है, अन्य धागे को अंतर्निहित संसाधन (आपके httpContext) का उपयोग करने से रोकने से रोकता है। । आशा है कि ये आपकी मदद करेगा।

+0

अल इस लॉकिंग को व्यवस्थित करना मुश्किल होगा, वह जो थ्रेडिंग अपवाद प्राप्त कर रहा है वह पृष्ठ क्लास से है, जो http संदर्भ को म्यूट कर रहा है, जब तक कि वह ऐसा करने वाले पेज में कार्रवाई को ओवरराइड नहीं कर सकता, और फिर लॉक रखता है लॉकिंग समाधान काम नहीं करेगा। – meandmycode

+1

ग्रेट टिप्पणी, मैं आपसे सहमत हूं। मेरी प्राथमिकता एक पूरी तरह से नई वस्तु को पारित करना होगा जो चलती रचना के समय HTTP संदर्भ से इसकी कुछ जानकारी प्राप्त करता है। वह बुलेट सबूत होगा। –

4

जबकि HttpContext को उस संदर्भ को संभालने के लिए डिज़ाइन किया गया है जो थ्रेड विशिष्ट नहीं है (क्योंकि http संदर्भ एक थ्रेड पर शुरू हो सकता है और दूसरे पर समाप्त हो सकता है), यह स्पष्ट रूप से थ्रेड सुरक्षित नहीं है।

अनिवार्य रूप से समस्या यह है कि आप ऐसा कुछ कर रहे हैं जिसका इरादा नहीं है, ये अनुरोध कई आम होंगे और प्रत्येक के पास अनुरोध पूरा करने के लिए अपना स्वयं का असाइन किया गया है, और प्रत्येक के पास अपना स्वयं का HttpContext है।

मैं वास्तव में कोशिश करता हूं और एएसपीनेट आधारभूत संरचना अनुरोधों को स्वयं प्रतिनिधि करता हूं।

1

चूंकि एचटीपीसीएन्टेक्स्ट .Net लाइब्रेरी का हिस्सा है, इसलिए मैं उम्मीद करता हूं कि सभी स्थैतिक कार्य थ्रेडसेफ हैं लेकिन किसी भी गैर स्थैतिक सदस्य ऑब्जेक्ट के उसी उदाहरण के विरुद्ध कॉल करते समय थ्रेडसेफ नहीं हैं। तो उम्मीद है कि अगली बार जब आप अनुमान लगाएंगे कि थ्रेड में HttpContext उदाहरण साझा करना समस्याएं होंगी।

क्या कोई तरीका है कि आप HttpContext से समानांतर में किए जाने वाले संचालन को रद्द कर सकते हैं? अगर वे सिर्फ डेटा लोड कर रहे हैं और सीएसवी प्रारूप में लिख रहे हैं, तो उस कोड के पास एएसपी.नेट उपयोगकर्ता नियंत्रण या पृष्ठ जीवन चक्र पर कोई आवश्यक निर्भरता नहीं है। एक बार उस निर्भरता को हटा दिए जाने के बाद, आप पृष्ठ को एसिंक्रोनस एचटीपीएचंडलर के साथ कार्यान्वित कर सकते हैं, IHttpHandler.BeginProcessingRequest() और IHttpHandler.EndProcessingRequest() के बीच समानांतर संचालन चला रहा है।

1

मैं यह सुनिश्चित करता हूं कि जब भी आप HttpContext.Current.Items संग्रह तक पहुंचें, तो आप HttpContext.Current.Items.SyncRoot ऑब्जेक्ट पर मॉनिटर लॉक (सी #)/सिंकलॉक (वीबी) ब्लॉक का उपयोग अपनी कॉल को लपेटने के लिए करते हैं।