2015-05-22 8 views
9

मुझे पता है कि यह एक आम सवाल है, लेकिन मैंने लेखों का एक किलो पढ़ा है और उलझन में महसूस किया है। और अब मुझे लगता है कि उन्हें बेहतर नहीं पढ़ना बेहतर होगा))।एएसपी.नेट और एसिंक - यह कैसे काम करता है?

तो, कैसे ASP.NET काम करता है (केवल धागे के बारे में):

  1. http अनुरोध थ्रेड पूल से धागा सेवा देती हैं।
  2. अनुरोध करते समय अनुरोध इस थ्रेड में व्यस्त है, क्योंकि अनुरोध वास्तव में इस धागे के अंदर प्रसंस्करण कर रहा है।
  3. अनुरोध प्रसंस्करण समाप्त होने पर, थ्रेड थ्रेड पूल पर वापस आ जाता है, सर्वर प्रतिक्रिया भेजता है।

क्या यह वर्णित व्यवहार सही है?

जब मैं एएसपी.नेट एमवीसी नियंत्रक के अंदर नया कार्य शुरू करता हूं तो वास्तव में क्या होता है? T1 -

public ActionResult Index() 
{ 
    var task1 = Task.Factory.StartNew(() => DoSomeHeavyWork()); 
    return View(); 
} 

private static async Task DoSomeHeavyWork() 
{ 
    await Task.Delay(5000); 
} 
  1. नियंत्रक कार्रवाई धागा है कि मौजूदा अनुरोध को संसाधित करता है अंदर निष्पादित करने के लिए शुरू होता है।
  2. थ्रेड पूल कार्य 1 के लिए एक और थ्रेड (टी 2) आवंटित करता है।
  3. कार्य 1 टी 2 के अंदर "तुरंत" शुरू होता है।
  4. व्यू परिणाम "तत्काल" लौटाता है।
  5. एएसपी.नेट कुछ काम करता है, सर्वर प्रतिक्रिया भेजता है, टी 1 थ्रेड पूल पर लौटाता है, टी 2 अभी भी जिंदा है।
  6. कुछ समय बाद DoSomeHeavyWork समाप्त हो जाएगा, टी 2 थ्रेड थ्रेड पूल में वापस कर दिया जाएगा।

क्या यह सही है?

  1. कार्रवाई करने के लिए शुरू होता है:

    अब देता है async कार्रवाई

    public async Task<ActionResult> Index() 
    { 
        await DoSomeHeavyWork(); 
        return View(); 
    } 
    

    , मैं पिछले कोड नमूने के साथ अंतर है, लेकिन नहीं की प्रक्रिया को समझने के लिए लग रही है, इस उदाहरण में व्यवहार पीछा कर रहा है थ्रेड के अंदर निष्पादित करें जो वर्तमान अनुरोध को संसाधित करता है - टी 1।

  2. DoSomeHeavyWork "तत्काल" एक कार्य देता है, चलो इसे "task1" भी कहते हैं।
  3. टी 1 थ्रेड पूल पर लौटता है। DoSomeHeavyWork समाप्त होने के बाद
  4. , इंडेक्स कार्रवाई निष्पादित जारी है। इंडेक्स एक्शन निष्पादन के बाद
  5. सर्वर प्रतिक्रिया देगा।

कृपया व्याख्या 2 अंक और 5 के बीच हो रहा है क्या, प्रश्न हैं:

  1. DoSomeHeavyWork अंदर संसाधित किया जाता है task1 या जहां (जहां यह "प्रतीक्षित" है)? मुझे लगता है कि यह एक महत्वपूर्ण सवाल है।
  2. कौन सा थ्रेड प्रतीक्षा के बाद अनुरोध को संसाधित करना जारी रखेगा - थ्रेड पूल से कोई नया, सही?
  3. अनुरोध थ्रेड पूल से आवंटित थ्रेड का उत्पादन करता है, लेकिन प्रतिक्रिया तब तक नहीं भेजी जाएगी जब तक DoSomeHeavyWorkAsync समाप्त नहीं हो जाता है और इससे कोई फर्क नहीं पड़ता कि यह विधि किस विधि को निष्पादित करती है। दूसरे शब्दों में, एकल अनुरोध और एकल ठोस कार्य (DoSomeHeavyWork) के अनुसार async का उपयोग करने का कोई लाभ नहीं है। क्या यह सही है ?
  4. यदि पिछले कथन सही है, तो मुझे समझ में नहीं आता कि एसिंक एक ही एकल कार्य के साथ एकाधिक अनुरोधों के प्रदर्शन को बेहतर बना सकता है। मैं समझाने की कोशिश करूंगा। आइए मान लें कि थ्रेड पूल में अनुरोधों को संभालने के लिए 50 धागे उपलब्ध हैं। अनुरोध को थ्रेड पूल से कम से कम एक थ्रेड द्वारा संसाधित किया जाना चाहिए, अगर अनुरोध एक और थ्रेड शुरू करता है, तो उन सभी को थ्रेड पूल से लिया जाएगा, उदा। अनुरोध स्वयं को संसाधित करने के लिए एक धागा लेता है, समानांतर में 5 अलग-अलग कार्यों को शुरू करता है और उन सभी का इंतजार करता है, थ्रेड पूल में आने वाले अनुरोधों को संभालने के लिए 50 - 1 - 5 = 44 मुक्त धागे होंगे - इसलिए यह समानता है, हम एकल के लिए प्रदर्शन में सुधार कर सकते हैं अनुरोध करें, लेकिन हम उन अनुरोधों की संख्या को कम करते हैं जिन्हें संसाधित किया जा सकता है। तो एएसपी.नेट में अनुरोध प्रसंस्करण के अनुसार मुझे लगता है कि किसी भी तरह से कार्य शुरू होता है IO पूरा होने वाला थ्रेड एसिंक (टीएपी) का लक्ष्य प्राप्त कर सकता है। लेकिन IO पूर्णता धागा इस मामले में थ्रेड पूल थ्रेड को वापस कैसे कॉल करता है?
+0

'प्रतीक्षा' इस प्रश्न के लिए कुछ मूल्यवान उत्तर। – Xmindz

उत्तर

5

क्या यह वर्णित व्यवहार सही है?

हां।

क्या यह सही है?

हां।

DoSomeHeavyWork कार्य 1 के अंदर संसाधित किया गया है या जहां (जहां यह "प्रतीक्षा है")? मुझे लगता है कि यह एक महत्वपूर्ण सवाल है।

वर्तमान कोड से DoSomeHeavyWork अतुल्यकालिक रूप से Task.Delay को पूरा करने के लिए प्रतीक्षा करेगा। हां, यह थ्रेड-पूल द्वारा आवंटित एक ही थ्रेड पर होगा, यह किसी भी नए धागे को स्पिन नहीं करेगा। लेकिन इस बात की कोई गारंटी नहीं है कि यह समान धागा होगा, हालांकि।

कौन सा धागा प्रतीक्षा के बाद अनुरोध को संसाधित करना जारी रखेगा?

क्योंकि हम एएसपी.नेट के बारे में बात कर रहे हैं, यह HttpContext पर मार्शल के साथ एक मनमाना थ्रेड-पूल थ्रेड होगा। यदि यह WinForms या WPF ऐप था, तो आप await के बाद यूआई थ्रेड को फिर से मार देंगे, यह देखते हुए कि आप ConfigureAwait(false) का उपयोग नहीं करते हैं।

अनुरोध थ्रेड पूल से आवंटित धागा पैदा करता है, लेकिन जब तक DoSomeHeavyWorkAsync समाप्त हो गया है और यह कोई फर्क नहीं पड़ता जो सूत्र में इस विधि कार्यान्वित प्रतिक्रिया नहीं भेजा जाएगा। दूसरे शब्दों में, एकल अनुरोध और एकल कंक्रीट कार्य (DoSomeHeavyWork) के अनुसार async का उपयोग करने का कोई लाभ नहीं है। क्या यह सही है ?

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

लेकिन कैसे IO पूर्णता धागा इस मामले में थ्रेड पूल थ्रेड को वापस कॉल करता है?

आपको समांतरता और समरूपता को अलग करना होगा। यदि आपको समांतर में सीपीयू बाध्य काम करने के लिए गणना शक्ति की आवश्यकता है, तो एसिंक ऐसा उपकरण नहीं है जो इसे घटित करेगा। दूसरी तरफ, यदि आपके पास बहुत सारे समवर्ती आईओ बाध्य संचालन हैं, जैसे सीआरयूडी संचालन के लिए डेटाबेस को मारना, आप द्वारा एसिंक के उपयोग से लाभ प्राप्त कर सकते हैं जबकि आईओ ऑपरेशन निष्पादित कर रहा है। एसिंक के लिए यह प्रमुख कुंजी बिंदु है।

थ्रेड-पूल में आईओ पूर्णता धागे के साथ-साथ कार्यकर्ता धागे, जो आप ThreadPool.GetAvailableThreads का आह्वान करके देख सकते हैं। जब आप आईओ बाध्य संचालन का उपयोग करते हैं, तो कॉलबैक को पुनर्प्राप्त करने वाला थ्रेड आमतौर पर एक आईओ पूर्णता धागा है, और कार्यकर्ता धागा नहीं है। वे दोनों अलग पूल हैं।

+0

धन्यवाद, यह स्पष्ट है। एक और सवाल - यदि मैं थर्ड-पार्टी लाइब्रेरी का उपयोग करता हूं और इसमें विधि कहा जाता है उदा। कुछ MethodAsync जो प्रतीक्षा कर रहा है, तो क्या मुझे इसे प्रतीक्षा कीवर्ड के साथ लपेटना चाहिए या सीधे कुछ MethodAsync (...) पर कॉल करना चाहिए। परिणाम? असल में मुझे नहीं पता कि यह किसी भी आईओ ऑपरेशंस का उपयोग करता है या नहीं। – SamousPrime

+2

@ सैमसप्रिम आप [एसिंक कोड पर अवरुद्ध नहीं होना चाहिए] (http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html), यह आपको सभी प्रकार की समस्याओं का कारण बन सकता है , deadlocks सहित। 'प्रतीक्षा करें 'का प्रयोग करें। यदि आप सुनिश्चित नहीं हैं कि कोड क्या कर रहा है, तो आप हमेशा इसे .NET डिकंपेलर के साथ देख सकते हैं। –

+0

डेडलॉक्स के बारे में उपयोगी उदाहरण। लेकिन क्या "async" का अर्थ वास्तव में async कीवर्ड है या यह असीमित का सामान्य अर्थ है? मैं पूछता हूं क्योंकि निम्नलिखित नमूने में कोई डेडलॉक नहीं है 'सार्वजनिक एक्शन रिसैट इंडेक्स() { int t = job() परिणाम; रिटर्न व्यू ("इंडेक्स"); } निजी स्थैतिक कार्य नौकरी() { वापसी कार्य। रुन (() => कार्य। डेले (2000)। (टी => 1)); } ' – SamousPrime

संबंधित मुद्दे