ASP.NET MVC में एसिंक्रोनस ऑपरेशन करते हैं। .NET 4 पर थ्रेडपूल से एक थ्रेड का उपयोग करें


158

इस सवाल के बाद, यह ASP.NET MVC में async संचालन का उपयोग करते समय मुझे आरामदायक बनाता है। तो, मैंने उस पर दो ब्लॉग पोस्ट लिखे:

ASP.NET MVC पर अतुल्यकालिक संचालन के बारे में मेरे मन में बहुत सी गलतफहमियाँ हैं।

मैं हमेशा इस वाक्य को सुनता हूं: यदि ऑपरेशन अतुल्यकालिक रूप से चलता है तो आवेदन बेहतर पैमाने पर हो सकता है

और मैंने इस तरह के वाक्यों को बहुत सुना है: यदि आपके पास ट्रैफ़िक की एक बड़ी मात्रा है, तो आप अपने प्रश्नों को अतुल्यकालिक रूप से नहीं करने से बेहतर हो सकते हैं - एक अनुरोध सेवा के लिए 2 अतिरिक्त थ्रेड का सेवन संसाधनों को अन्य आने वाले अनुरोधों से दूर ले जाता है।

मुझे लगता है कि वे दो वाक्य असंगत हैं।

मुझे इस बारे में अधिक जानकारी नहीं है कि ASP.NET पर थ्रेडपूल कैसे काम करता है, लेकिन मुझे पता है कि थ्रेडपूल थ्रेड्स के लिए एक सीमित आकार है। तो, दूसरा वाक्य इस मुद्दे से संबंधित होना चाहिए।

और मैं जानना चाहूंगा कि क्या ASP.NET MVC में अतुल्यकालिक संचालन .NET 4 पर थ्रेडपूल से एक थ्रेड का उपयोग करता है?

उदाहरण के लिए, जब हम एक AsyncController को लागू करते हैं, तो ऐप कैसे संरचना करता है? यदि मुझे बहुत अधिक ट्रैफ़िक मिलता है, तो क्या AsyncController को लागू करना एक अच्छा विचार है?

क्या कोई ऐसा व्यक्ति है जो मेरी आँखों के सामने इस काले पर्दे को हटा सकता है और मुझे ASP.NET MVC 3 (NET 4) पर अतुल्यकालिक के बारे में समझा सकता है?

संपादित करें:

मैंने इस दस्तावेज़ को लगभग सैकड़ों बार पढ़ा है और मैं मुख्य सौदे को समझता हूं लेकिन फिर भी मुझे भ्रम है क्योंकि वहाँ बहुत अधिक असंगत टिप्पणी है।

ASP.NET MVC में एक अतुल्यकालिक नियंत्रक का उपयोग करना

संपादित करें:

मान लें कि मेरे पास नीचे की तरह नियंत्रक कार्रवाई है ( AsyncControllerहालांकि कार्यान्वयन नहीं ):

public ViewResult Index() { 

    Task.Factory.StartNew(() => { 
        //Do an advanced looging here which takes a while
    });

    return View();
}

जैसा कि आप यहां देख रहे हैं, मैं एक ऑपरेशन में आग लगाता हूं और इसके बारे में भूल जाता हूं। फिर, मैं इसे पूरा किए बिना इंतजार किए तुरंत लौट जाता हूं।

इस मामले में, क्या इसे थ्रेडपूल से एक धागे का उपयोग करना है? यदि हां, तो इसके पूरा होने के बाद, उस धागे का क्या होता है? क्या GCयह पूरा होने के बाद ही अंदर आता है और सफाई करता है?

संपादित करें:

@ डारिन के जवाब के लिए, यहां async कोड का एक नमूना है जो डेटाबेस से बात करता है:

public class FooController : AsyncController {

    //EF 4.2 DbContext instance
    MyContext _context = new MyContext();

    public void IndexAsync() { 

        AsyncManager.OutstandingOperations.Increment(3);

        Task<IEnumerable<Foo>>.Factory.StartNew(() => { 

           return 
                _context.Foos;
        }).ContinueWith(t => {

            AsyncManager.Parameters["foos"] = t.Result;
            AsyncManager.OutstandingOperations.Decrement();
        });

        Task<IEnumerable<Bars>>.Factory.StartNew(() => { 

           return 
                _context.Bars;
        }).ContinueWith(t => {

            AsyncManager.Parameters["bars"] = t.Result;
            AsyncManager.OutstandingOperations.Decrement();
        });

        Task<IEnumerable<FooBar>>.Factory.StartNew(() => { 

           return 
                _context.FooBars;
        }).ContinueWith(t => {

            AsyncManager.Parameters["foobars"] = t.Result;
            AsyncManager.OutstandingOperations.Decrement();
        });
    }

    public ViewResult IndexCompleted(
        IEnumerable<Foo> foos, 
        IEnumerable<Bar> bars,
        IEnumerable<FooBar> foobars) {

        //Do the regular stuff and return

    }
}

उत्तर पर निश्चित नहीं है, लेकिन इसके अतुल्यकालिक और मल्टी-थ्रेडिंग के लायक अलग-अलग चीजें हैं। इसलिए एसिंक्रोनस हैंडलिंग के साथ थ्रेड्स की एक निश्चित संख्या होना संभव होगा। क्या होगा जब एक पृष्ठ को कहने के लिए ब्लॉक करना होगा, I / O, दूसरे पृष्ठ को उसी धागे पर चलने का मौका मिलेगा। जो उन दोनों कथनों को सही हो सकता है, async चीजों को तेज कर सकते हैं लेकिन बहुत सारे धागे एक समस्या है।
13:55 पर क्रिस चिलवर्स

@ChrisChilvers हां, एसिंक्रोनस ऑपरेशन पर हमेशा मल्टीथ्रेडिंग आवश्यक नहीं है। मैंने पहले ही पता लगा लिया है लेकिन मुझे लगता है कि मेरे पास कोई नियंत्रक नहीं है जहां तक ​​मैं बता सकता हूं। AsyncController स्पिन यह मेरे दृष्टिकोण से कितने धागे चाहता है, लेकिन उस पर भी सुनिश्चित नहीं है। क्या WPF जैसे डेस्कटॉप ऐप्स पर थ्रेडपूल की एक धारणा है? मुझे लगता है कि थ्रेड्स की संख्या इस तरह के ऐप्स पर कोई समस्या नहीं है।
tugberk


मुझे लगता है कि समस्या (और इस तरह असंगतता) दूसरा कथन अतुल्यकालिक का उपयोग करता है जब इसका अर्थ है कई धागे। ऐसा इसलिए हो सकता है क्योंकि इस तरह से asp.net ने async पेजों को लागू किया है और इस प्रकार विशिष्ट कार्यान्वयन ने समस्या को भ्रमित कर दिया है (क्योंकि समस्या का कारण बनने वाले फ़ीचर का नाम async पेज होगा), लेकिन मैं विशिष्ट कार्यान्वयन के बारे में निश्चित नहीं हूं । इसलिए या तो उनका मतलब है "कई धागे", या उनका मतलब है "एस्पेन पेजों के भीतर asp.net संस्करण X" क्योंकि भविष्य के संस्करण कार्यान्वयन को बदल सकते हैं। या वे सिर्फ एक पृष्ठ के भीतर async प्रदर्शन करने के लिए थ्रेड पूल का उपयोग कर रहे हैं।
क्रिस चिलवर्स

@ क्रिसचिलवर्स ओह, यार! इन टिप्पणियों के बाद मैं और अधिक भ्रमित हूँ: s
tugberk

जवाबों:


177

यहां एक उत्कृष्ट लेख है जो मैं आपको ASP.NET में अतुल्यकालिक प्रसंस्करण को बेहतर ढंग से समझने के लिए पढ़ने की सलाह दूंगा (जो मूल रूप से अतुल्यकालिक नियंत्रक है)।

आइए पहले एक मानक तुल्यकालिक कार्रवाई पर विचार करें:

public ActionResult Index()
{
    // some processing
    return View();
}

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

अब अतुल्यकालिक पैटर्न का एक उदाहरण लेते हैं:

public void IndexAsync()
{
    // perform some processing
}

public ActionResult IndexCompleted(object result)
{
    return View();
}

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

तो इस पैटर्न में हम जो देख सकते हैं वह यह है कि एक ही क्लाइंट HTTP रिक्वेस्ट को दो अलग-अलग थ्रेड द्वारा निष्पादित किया जा सकता है।

अब दिलचस्प हिस्सा IndexAsyncविधि के अंदर होता है । यदि आपके पास इसके अंदर एक ब्लॉकिंग ऑपरेशन है, तो आप एसिंक्रोनस कंट्रोलर्स के पूरे उद्देश्य को पूरी तरह से बर्बाद कर रहे हैं क्योंकि आप वर्कर थ्रेड को रोक रहे हैं (याद रखें कि इस क्रिया के बॉडी को थ्रेड पूल से निकाले गए थ्रेड पर निष्पादित किया जाता है)।

तो हम अतुल्यकालिक नियंत्रकों का वास्तविक लाभ कब ले सकते हैं?

IMHO हम सबसे अधिक लाभ प्राप्त कर सकते हैं जब हमारे पास I / O गहन संचालन (जैसे डेटाबेस और दूरस्थ सेवाओं के लिए नेटवर्क कॉल) है। यदि आपके पास CPU गहन संचालन है, तो एसिंक्रोनस क्रियाएँ आपको अधिक लाभ नहीं पहुंचाएंगी।

तो हम I / O गहन परिचालन से लाभ क्यों प्राप्त कर सकते हैं? क्योंकि हम I / O पूर्णता पोर्ट का उपयोग कर सकते हैं । IOCP बेहद शक्तिशाली है क्योंकि आप पूरे ऑपरेशन के निष्पादन के दौरान सर्वर पर किसी भी थ्रेड या संसाधनों का उपभोग नहीं करते हैं।

वो कैसे काम करते है?

मान लीजिए कि हम WebClient.DownloadStringAsync विधि का उपयोग करके एक दूरस्थ वेब पेज की सामग्री डाउनलोड करना चाहते हैं । आप इस पद्धति को कॉल करते हैं जो ऑपरेटिंग सिस्टम के भीतर एक IOCP पंजीकृत करेगा और तुरंत वापस आ जाएगा। पूरे अनुरोध के प्रसंस्करण के दौरान, आपके सर्वर पर किसी भी थ्रेड का उपभोग नहीं किया जाता है। रिमोट सर्वर पर सब कुछ होता है। इसमें बहुत समय लग सकता है, लेकिन आपको परवाह नहीं है क्योंकि आप अपने कार्यकर्ता धागे को खतरे में नहीं डाल रहे हैं। एक प्रतिक्रिया प्राप्त होने के बाद IOCP को संकेत दिया जाता है, थ्रेड पूल से एक थ्रेड खींचा जाता है और इस थ्रेड पर कॉलबैक निष्पादित होता है। लेकिन जैसा कि आप देख सकते हैं, पूरी प्रक्रिया के दौरान, हमने किसी भी धागे का एकाधिकार नहीं किया है।

वही FileStream.BeginRead, SqlCommand.BeginExute, ... जैसे तरीकों के साथ सच है

कई डेटाबेस कॉल को समानांतर करने के बारे में क्या? मान लीजिए कि आपके पास एक तुल्यकालिक नियंत्रक कार्रवाई थी जिसमें आपने 4 अवरुद्ध डेटाबेस कॉल को अनुक्रम में किया था। यह गणना करना आसान है कि यदि प्रत्येक डेटाबेस कॉल 200ms लेता है, तो आपकी नियंत्रक कार्रवाई को निष्पादित करने में लगभग 800ms लगेंगे।

यदि आपको क्रमिक रूप से उन कॉल्स को चलाने की आवश्यकता नहीं है, तो क्या इससे उनके प्रदर्शन में सुधार होगा?

यह बड़ा सवाल है, जिसका जवाब देना आसान नहीं है। शायद हां, शायद नहीं। यह पूरी तरह से इस बात पर निर्भर करेगा कि आप उन डेटाबेस कॉल्स को कैसे लागू करते हैं। यदि आप async नियंत्रकों और I / O पूर्णता पोर्ट का उपयोग करते हैं जैसा कि पहले चर्चा की गई है कि आप इस नियंत्रक कार्रवाई और अन्य कार्यों के प्रदर्शन को बढ़ावा देंगे, साथ ही साथ आप वर्कर थ्रेड का एकाधिकार नहीं करेंगे।

दूसरी ओर यदि आप उन्हें खराब तरीके से कार्यान्वित करते हैं (थ्रेड पूल से थ्रेड पर किए गए ब्लॉकिंग डेटाबेस कॉल के साथ), तो आप मूल रूप से इस कार्रवाई के निष्पादन का कुल समय लगभग 200ms तक कम कर देंगे, लेकिन आपने 4 वर्कर थ्रेड का सेवन किया होगा ताकि आप हो सकता है कि अन्य अनुरोधों के प्रदर्शन को कम कर दिया जाए जो उन्हें संसाधित करने के लिए पूल में लापता धागे के कारण भूखे हो सकते हैं।

इसलिए यह बहुत मुश्किल है और यदि आप अपने आवेदन पर व्यापक परीक्षण करने के लिए तैयार नहीं हैं, तो अतुल्यकालिक नियंत्रकों को लागू न करें, क्योंकि संभावना है कि आप लाभ की तुलना में अधिक नुकसान करेंगे। उन्हें केवल तभी लागू करें जब आपके पास ऐसा करने का कोई कारण हो: उदाहरण के लिए आपने पहचान लिया है कि मानक तुल्यकालिक नियंत्रक क्रियाएं आपके आवेदन के लिए एक अड़चन हैं (व्यापक भार परीक्षण और पाठ्यक्रम के माप के प्रदर्शन के बाद)।

अब आप अपने उदाहरण पर विचार करें:

public ViewResult Index() { 

    Task.Factory.StartNew(() => { 
        //Do an advanced looging here which takes a while
    });

    return View();
}

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

अब निम्नलिखित पर विचार करें:

public ViewResult Index() { 

    new Thread(() => { 
        //Do an advanced looging here which takes a while
    }).Start();

    return View();
}

इस मामले में हम मैन्युअल रूप से एक धागा पैदा कर रहे हैं। इस मामले में सूचकांक कार्रवाई के शरीर का निष्पादन थोड़ा अधिक समय ले सकता है (क्योंकि एक नया धागा पैदा करना मौजूदा पूल से एक ड्राइंग की तुलना में अधिक महंगा है)। लेकिन उन्नत लॉगिंग ऑपरेशन का निष्पादन एक थ्रेड पर किया जाएगा जो पूल का हिस्सा नहीं है। इसलिए हम पूल से धागे को खतरे में नहीं डाल रहे हैं जो अन्य अनुरोधों की सेवा के लिए स्वतंत्र हैं।


1
वास्तव में विस्तृत, धन्यवाद! मान लेते हैं कि, हमारे पास 4 async टास्क ( System.Threading.Task) IndexAsyncविधि के अंदर चल रहे हैं । उन परिचालनों के अंदर, हम सर्वर पर db कॉल कर रहे हैं। तो, वे सभी I / O सघन ऑपरेशन हैं, है ना? उस स्थिति में, क्या हम 4 अलग धागे बनाते हैं (या थ्रेड-पूल से 4 अलग धागे मिलते हैं)? मान लें कि मेरे पास एक मल्टी-कोर मशीन है जो वे समानांतर में भी चलने वाली हैं, है ना?
टुगर्क

10
@tugberk, डेटाबेस कॉल I / O ऑपरेशन हैं, लेकिन यह सब इस बात पर निर्भर करेगा कि आप उन्हें कैसे लागू करते हैं। यदि आप एक अवरुद्ध डेटाबेस कॉल का उपयोग SqlCommand.ExecuteReaderकरते हैं जैसे कि आप सब कुछ बर्बाद कर रहे हैं क्योंकि यह एक अवरुद्ध कॉल है। आप उस थ्रेड को रोक रहे हैं जिस पर यह कॉल निष्पादित होता है और यदि यह थ्रेड पूल से एक थ्रेड होता है तो यह बहुत बुरा है। आप केवल तभी लाभान्वित होंगे जब आप I / O पूर्णता पोर्ट का उपयोग करेंगे SqlCommand.BeginExecuteReader:। यदि आप IOCP का उपयोग नहीं करते हैं तो आप क्या करते हैं, async नियंत्रकों का उपयोग न करें क्योंकि आप अपने आवेदन के समग्र प्रदर्शन पर लाभ की तुलना में अधिक नुकसान करेंगे।
डारिन दिमित्रोव

1
खैर, ज्यादातर समय मैं पहले ईएफ कोड का उपयोग करता हूं। मुझे यकीन नहीं है कि यह फिट बैठता है। मैंने एक नमूना रखा जो दिखाता है कि मैं आमतौर पर क्या करता हूं। मैंने सवाल अपडेट किया, क्या आप देख सकते हैं?
tugberk

3
@tugberk, आप उन्हें समानांतर में चला रहे हैं, इसलिए यदि आप उन्हें क्रमिक रूप से चलाते हैं, तो निष्पादन का कुल समय कम है। लेकिन इन्हें चलाने के लिए आप वर्कर थ्रेड का इस्तेमाल करते हैं। वास्तव में ईएफ आलसी है इसलिए जब आप करते _context.Fooहैं तो आप वास्तव में कुछ भी निष्पादित नहीं कर रहे हैं। आप सिर्फ एक अभिव्यक्ति वृक्ष का निर्माण कर रहे हैं। इससे बेहद सावधान रहें। क्वेरी निष्पादन केवल तभी स्थगित किया जाता है जब आप परिणाम पर गणना शुरू करते हैं। और अगर ऐसा होता है तो यह प्रदर्शन के लिए विनाशकारी हो सकता है। उत्सुकता .ToList()से अंत में एक ईएफ क्वेरी संलग्न करें।
डारिन दिमित्रोव

2
@tugberk, आपको लोड परीक्षण उपकरण की आवश्यकता होगी ताकि वह अपनी वेब साइट पर समानांतर में कई उपयोगकर्ताओं को अनुकरण करने के लिए यह देख सके कि यह भारी भार के तहत कैसे व्यवहार करता है। मिनी Profiler आपकी वेबसाइट पर लोड अनुकरण नहीं कर सकता। यह आपको अपने ADO.NET प्रश्नों को देखने और अनुकूलित करने में मदद कर सकता है और एक एकल अनुरोध को प्रोफ़ाइल कर सकता है जो तब बेकार होता है जब आपको यह देखने की आवश्यकता होती है कि आपकी साइट वास्तविक दुनिया की स्थिति में कैसे व्यवहार करती है जब बहुत सारे उपयोगकर्ता इसे मार रहे हों।
डारिन दिमित्रोव

49

हां - सभी धागे थ्रेड-पूल से आते हैं। आपका MVC ऐप पहले से ही बहु-थ्रेडेड है, जब एक नया थ्रेड में एक अनुरोध आता है जिसे पूल से लिया जाएगा और अनुरोध को सेवा देने के लिए उपयोग किया जाएगा। वह धागा 'लॉक' (अन्य अनुरोधों से) होगा जब तक कि अनुरोध पूरी तरह से सेवित और पूरा नहीं हो जाता। यदि पूल में कोई धागा उपलब्ध नहीं है, तो अनुरोध तब तक इंतजार करना होगा जब तक कि एक उपलब्ध न हो।

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

अंतर यह है कि यदि आपके पास बहुत लंबे समय से चल रहे अनुरोध हैं (जहां थ्रेड किसी चीज की प्रतिक्रिया की प्रतीक्षा कर रहा है) तो आप बुनियादी अनुरोधों को पूरा करने के लिए पूल से थ्रेड्स से बाहर भी भाग सकते हैं। यदि आपके पास async नियंत्रक है, तो आपके पास और अधिक धागे नहीं हैं, लेकिन वे धागे जो प्रतीक्षा कर रहे हैं, वे पूल में वापस आ गए हैं और अन्य अनुरोधों को सेवा दे सकते हैं।

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

बिना एसिंक्स कंट्रोलर के, आपके पीछे के यात्रियों को आपके पैसे की तलाश करते समय उम्र का इंतजार करना होगा, इस बीच बस चालक कोई काम नहीं करेगा।

इसलिए निष्कर्ष यह है, अगर बहुत से लोग यह नहीं जानते हैं कि उनका पैसा कहां है (यानी ड्राइवर को किसी चीज का जवाब देने के लिए लंबे समय की आवश्यकता होती है) तो एसिंक्स कंट्रोलर अनुरोधों के थ्रूपुट की अच्छी तरह से मदद कर सकते हैं, कुछ से प्रक्रिया को तेज कर सकते हैं। बिना aysnc कंट्रोलर के हर कोई इंतजार करता है जब तक सामने वाले व्यक्ति को पूरी तरह से निपटा नहीं दिया जाता है। लेकिन यह मत भूलो कि एमवीसी में आपके पास एक ही बस में बहुत सारे बस ड्राइवर हैं, इसलिए एसिंक्स एक स्वचालित विकल्प नहीं है।


8
बहुत अच्छा सादृश्य। धन्यवाद।
पिट्सबर्ग डीबीए

मुझे विवरण पसंद आया। धन्यवाद
ओमर कांसिज़ोग्लू

इसे समझाने का उत्कृष्ट तरीका है। धन्यवाद,
आनंद व्यास

डारिन के उत्तर के संयोजन में आपका जवाब पूरे तंत्र को async नियंत्रकों के पीछे रखता है, यह क्या है, और अधिक महत्वपूर्ण बात यह है कि यह क्या नहीं है!
निर्मण

यह एक अच्छा सादृश्य है, लेकिन मेरा एकमात्र सवाल यह है: आपकी सादृश्य में अपनी जेब में लड़खड़ाता हुआ आदमी हमारे आवेदन में किसी प्रकार का कार्य / प्रसंस्करण होगा ... तो क्या एक बार जब हम थ्रेड जारी करते हैं तो क्या प्रक्रियाएं होती हैं? सूरीली यह एक और धागा है? तो हम यहाँ क्या हासिल करते हैं?
टोमुके

10

यहाँ पर दो अवधारणाएँ हैं। सबसे पहले हम उपयोगकर्ता को प्रतीक्षा करने से बचने के लिए किसी अन्य थ्रेड पर तेज़ या शेड्यूल कोड निष्पादित करने के लिए समानांतर में अपना कोड रन कर सकते हैं। जो उदाहरण आपके पास था

public ViewResult Index() { 

    Task.Factory.StartNew(() => { 
        //Do an advanced looging here which takes a while
    });

    return View();
}

दूसरी श्रेणी का है। उपयोगकर्ता को तेजी से प्रतिक्रिया मिलेगी लेकिन सर्वर पर कुल काम का बोझ अधिक है क्योंकि इसे एक ही काम करना है + थ्रेडिंग को संभालना है।

इसका एक और उदाहरण होगा:

public ViewResult Index() { 

    Task.Factory.StartNew(() => { 
        //Make async web request to twitter with WebClient.DownloadString()
    });

    Task.Factory.StartNew(() => { 
        //Make async web request to facebook with WebClient.DownloadString()
    });


    //wait for both to be ready and merge the results

    return View();
}

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

यह क्लाइंट परिदृश्य में पूरी तरह से ठीक है। और एक नए कार्य में सिंक्रोनस लॉन्ग रनिंग कोड को लपेटना काफी आम है (इसे किसी अन्य थ्रेड पर चलाएं) ui को उत्तरदायी बनाएं या इसे तेज करने के लिए लंबित करें। एक धागा अभी भी पूरी अवधि के लिए उपयोग किया जाता है। उच्च भार वाले सर्वर पर यह बैकफ़ायर कर सकता है क्योंकि आप वास्तव में अधिक संसाधनों का उपयोग करते हैं। यह वही है जिसके बारे में लोगों ने आपको चेतावनी दी है

हालांकि MVC में Async नियंत्रकों का एक और लक्ष्य है। यहाँ बिंदु कुछ भी नहीं करने के लिए थ्रेडिंग बैठने से बचने के लिए है (जो स्केलेबिलिटी को नुकसान पहुंचा सकता है)। यह वास्तव में केवल तभी मायने रखता है जब एपीआई के आप कॉल कर रहे हैं, जिसमें एसिंक्स तरीके हैं। जैसे WebClient.DowloadStringAsync ()।

मुद्दा यह है कि आप अपने अनुरोध को नए अनुरोधों को संभालने के लिए वापस कर सकते हैं जब तक कि वेब अनुरोध समाप्त न हो जाए, जहां यह आपको कॉलबैक कहेगा जो समान या नया धागा प्राप्त करता है और अनुरोध को पूरा करता है।

मुझे आशा है कि आप अतुल्यकालिक और समानांतर के बीच अंतर को समझेंगे। समानांतर कोड के बारे में सोचें, जहां आपका धागा आसपास बैठता है और परिणाम की प्रतीक्षा करता है। जबकि एसिंक्रोनस कोड वह कोड होता है जहां आपको कोड होने पर सूचित किया जाएगा और आप इस पर वापस काम कर सकते हैं, इस बीच धागा अन्य काम कर सकता है।


6

यदि ऑपरेशन अतुल्यकालिक रूप से चलते हैं, तो अनुप्रयोग बेहतर पैमाने पर हो सकते हैं , लेकिन अगर अतिरिक्त संसाधन उपलब्ध कराने के लिए संसाधन उपलब्ध हैं

अतुल्यकालिक संचालन सुनिश्चित करते हैं कि आप कभी भी किसी कार्रवाई को रोक नहीं रहे हैं क्योंकि एक मौजूदा एक प्रगति पर है। ASP.NET के पास एक अतुल्यकालिक मॉडल है जो कई अनुरोधों को साइड-बाय-साइड निष्पादित करने की अनुमति देता है। अनुरोधों को पंक्तिबद्ध करना और उन्हें FIFO संसाधित करना संभव होगा, लेकिन जब आप सैकड़ों अनुरोधों को पंक्तिबद्ध करते हैं तो यह अच्छी तरह से स्केल नहीं होगा और प्रत्येक अनुरोध प्रक्रिया के लिए 100ms लेता है।

आप यातायात की एक बड़ी मात्रा है, तो आप कर सकते हैं बेहतर बंद एसिंक्रोनस रूप से आपके प्रश्नों प्रदर्शन नहीं कर रहा, हो के रूप में वहाँ अनुरोध सेवा करने के लिए कोई अतिरिक्त संसाधन हो सकता है । यदि कोई अतिरिक्त संसाधन नहीं हैं, तो आपके अनुरोधों को कतारबद्ध करने के लिए मजबूर किया जाता है, तेजी से लंबा या एकमुश्त विफल हो जाता है, जिस स्थिति में अतुल्यकालिक ओवरहेड (म्यूटेक्स और संदर्भ-स्विचिंग ऑपरेशन) आपको कुछ भी नहीं दे रहा है।

जहाँ तक ASP.NET जाता है, आपके पास कोई विकल्प नहीं है - यह एक अतुल्यकालिक मॉडल का उपयोग करता है, क्योंकि यही वह है जो सर्वर-क्लाइंट मॉडल के लिए समझ में आता है। यदि आप अपने स्वयं के कोड को आंतरिक रूप से लिख रहे थे जो बेहतर पैमाने पर करने के लिए एक async पैटर्न का उपयोग करता है, जब तक कि आप सभी अनुरोधों के बीच साझा किए गए संसाधन को प्रबंधित करने का प्रयास नहीं कर रहे हैं, आप वास्तव में कोई सुधार नहीं देखेंगे क्योंकि वे पहले से ही लिपटे हुए हैं। एक अतुल्यकालिक प्रक्रिया में जो कुछ और ब्लॉक नहीं करता है।

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

संपादित करें:

आपके उदाहरण में, Task.Factory.StartNewकॉल .NET थ्रेड-पूल पर एक ऑपरेशन को कतारबद्ध करेगी। थ्रेड पूल थ्रेड्स की प्रकृति को फिर से उपयोग किया जाना है (बहुत सारे थ्रेड बनाने / नष्ट करने की लागत से बचने के लिए)। एक बार जब ऑपरेशन पूरा हो जाता है, तो थ्रेड वापस पूल में जारी किया जाता है एक और अनुरोध के द्वारा उपयोग किया जाता है (कचरा कलेक्टर वास्तव में शामिल नहीं होता है जब तक कि आप अपने ऑपरेशन में कुछ ऑब्जेक्ट नहीं बनाते हैं, जिस स्थिति में वे सामान्य रूप से एकत्र किए जाते हैं। scoping)।

जहाँ तक ASP.NET की बात है, यहाँ कोई विशेष ऑपरेशन नहीं है। ASP.NET अनुरोध एसिंक्रोनस कार्य के लिए सम्मान के बिना पूरा करता है। एकमात्र चिंता यह हो सकती है कि क्या आपका थ्रेड पूल संतृप्त है (यानी अनुरोध अनुरोध करने के लिए अभी कोई थ्रेड उपलब्ध नहीं हैं और पूल की सेटिंग अधिक थ्रेड्स बनाने की अनुमति नहीं देती हैं), जिस स्थिति में अनुरोध को शुरू करने के इंतजार में अवरुद्ध कर दिया जाता है। पूल थ्रेड उपलब्ध होने तक कार्य करें


धन्यवाद! आपके उत्तर को पढ़ने के बाद, मैंने प्रश्न को एक कोड नमूने के साथ संपादित किया। क्या आप देख सकते हैं?
tugberk

मेरे लिए आपके पास एक जादू का वाक्य है: Task.Factory.StartNewकॉल .NET थ्रेड-पूल पर एक ऑपरेशन को कतारबद्ध करेगा। । इस संदर्भ में, कौन सा यहां सही है: 1-) यह एक नया धागा बनाता है और जब यह किया जाता है, तो वह धागा वापस थ्रेडपूल में जाता है और फिर से पुन: उपयोग होने की प्रतीक्षा करता है। 2-) इसे थ्रेडपूल से एक धागा मिलता है और वह धागा वापस थ्रेडपूल में जाता है और फिर से पुन: उपयोग होने की प्रतीक्षा करता है। 3-) यह सबसे कुशल तरीका अपनाता है और दोनों में से कोई भी कर सकता है।
टगबरक

1
थ्रेड-पूल आवश्यक होने पर थ्रेड बनाता है और थ्रेड को रीसायकल करता है जब उनका उपयोग नहीं किया जा रहा हो। यह सटीक व्यवहार सीएलआर संस्करणों में विविध है। आप इसके बारे में विशेष जानकारी यहाँ प्राप्त कर सकते हैं msdn.microsoft.com/en-us/library/0ka9477y.aspx
पॉल टर्नर

यह अब मेरे दिमाग में आकार लेने लगता है। तो, सीएलआर थ्रेड-पूल का मालिक है, है ना? उदाहरण के लिए, एक WPF एप्लीकेशन में थ्रेड-पूल की भी धारणा है और यह वहाँ के साथ-साथ पूल से भी संबंधित है।
टुगर्क

1
सीएलआर के भीतर थ्रेड पूल अपनी चीज है। अन्य घटक जो पूल के "जागरूक" हैं, संकेत दे रहे हैं कि वे थ्रेड पूल थ्रेड्स का उपयोग करते हैं (जहां उपयुक्त हो) अपने स्वयं के बनाने और नष्ट करने के बजाय। किसी धागे को बनाना या नष्ट करना एक अपेक्षाकृत महंगा ऑपरेशन है, इसलिए पूल का उपयोग शॉर्ट-रनिंग ऑपरेशन पर एक बड़ी दक्षता हासिल करता है।
पॉल टर्नर

2

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

http://msdn.microsoft.com/en-us/library/ee728598.aspx

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

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


मैंने उस दस्तावेज़ को शायद सैकड़ों बार पढ़ा है और अभी भी मुझे बहुत भ्रम है (शायद समस्या मुझे है, जो जानता है)। जब आप चारों ओर देखते हैं, तो आप ASP.NET MVC पर अतुल्यकालिक के बारे में इतनी असंगत टिप्पणियां देखते हैं जैसा कि आप मेरे प्रश्न पर देख सकते हैं।
tugberk

अंतिम वाक्य के लिए: एक कंट्रोलर एक्शन के अंदर, मैं एक डेटाबेस को 5 बार अलग-अलग (मुझे) करना था और यह सब लगभग 400 एमएस ले रहा था। फिर, मैंने AsyncController को लागू किया और उन्हें समानांतर में चलाया। प्रतिक्रिया समय नाटकीय रूप से लगभग कम हो गया। 200 मि। लेकिन मुझे नहीं पता कि यह कितने धागे का निर्माण करता है, उन थ्रेड्स के साथ क्या होता है जब मैं उनके साथ किया जाता हूं, तब GCआता है और मुझे ठीक करने के बाद उन्हें साफ करता है ताकि मेरे ऐप में मेमोरी लीक न हो, इसलिए आगे। उस हिस्से पर कोई विचार।
tugberk

डिबगर संलग्न करें और पता करें।
एआर

0

पहली बात इसके MVC नहीं बल्कि IIS जो थ्रेड पूल को बनाए रखता है। इसलिए एमवीसी या एएसपी.नेट एप्लिकेशन के लिए आने वाले किसी भी अनुरोध को थ्रेड से जो थ्रेड पूल में बनाए रखा जाता है। केवल ऐप Asynch बनाने के साथ वह इस क्रिया को एक अलग थ्रेड में आमंत्रित करता है और थ्रेड को तुरंत रिलीज़ करता है ताकि अन्य अनुरोध लिए जा सकें।

मैंने एक डिटेल वीडियो ( http://www.youtube.com/watch?v=wvg13n5V0V0// "MVC Asynch नियंत्रकों और थ्रेड भुखमरी") के साथ यही समझाया है, जो दिखाता है कि MVC में थ्रेड भुखमरी कैसे होती है और MVC का उपयोग करके कैसे कम किया जाता है Asynch नियंत्रकों.मैंने भी perfmon का उपयोग करके अनुरोध कतारों को मापा है ताकि आप देख सकें कि MVC asynch के लिए अनुरोध कतारें कैसे घटती हैं और Synch संचालन के लिए इसकी स्थिति कितनी खराब है।

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