2013-05-21 21 views
12

मेरे पास एक उच्च-ट्रैफिक सी # एमवीसी 4 वेब एप्लिकेशन है जो उच्च-ट्रैफिक परिदृश्य में है जो विभिन्न भंडारों के लिए निर्भरता इंजेक्शन का उपयोग करता है। यह बहुत उपयोगी है क्योंकि यह आसानी से परीक्षण योग्य है, और उत्पादन में हम विशिष्ट नियंत्रकों के लिए आसानी से भंडार को कॉन्फ़िगर कर सकते हैं। सभी नियंत्रक AsyncController से प्राप्त होते हैं, इसलिए Task<JsonResult> या Task<ActionResult> लौटने वाली क्रिया विधियां वास्तव में अधिक उपयोगकर्ताओं और solve for the dreaded thread starvation problem के साथ हमारे सर्वर पैमाने की सहायता करती हैं। कुछ रिपॉजिटरीज वेब सेवाओं का उपयोग करते हैं, जिन्हें हम स्केलेबिलिटी लाभ प्रदान करने के लिए निश्चित रूप से Async/Await का उपयोग कर सकते हैं। अन्य मामलों में, कुछ अप्रबंधित सेवाओं का उपयोग कर सकते हैं जिन्हें सुरक्षित रूप से थ्रेड नहीं किया जा सकता है, जिसमें async/await कोई लाभ नहीं प्रदान करेगा। प्रत्येक भंडार एक इंटरफ़ेस, आईरिपोजिटरी का कार्यान्वयन है। संक्षेप में, प्रत्येक कार्यान्वयन डेटा प्राप्त करने के तरीके में काफी अलग है। यह कॉन्फ़िगरेशन वेब.कॉन्फिग परिवर्तन और ऑटोफ़ैक मॉड्यूल के साथ परिनियोजन-समय पर चुना जाता है।बहु-परत सी # अनुप्रयोगों में Async/Await

इस तरह के किसी एप्लिकेशन में async/प्रतीक्षा करने के लिए सुझाए गए कुछ तरीके क्या हैं? पैटर्न को मेरे मौजूदा एप्लिकेशन में फिट करने के लिए, मुझे Task<MyBusinessObject> वापस करने के लिए इंटरफ़ेस को बदलना होगा। लेकिन क्या यह कार्यान्वयन विस्तार से अधिक नहीं है? मैं दो विधि स्टब्स, GetData और GetDataAsync प्रदान कर सकता हूं, लेकिन मेरे लिए जो अब लचीलापन की अनुमति नहीं देगा IOC फ्रेमवर्क जैसे ऑटोफैक के साथ जहां मैं आसानी से कोड बदलने के बिना सबकुछ बाहर कर सकता हूं।

असिनक/Await के लिए माइक्रोसॉफ्ट डेवलपर्स में से एक ने ब्लॉग पोस्ट प्रकाशित किया है, "Should I expose an asynchronous wrapper for my synchronous methods?" उस तरह की समस्या में चला जाता है। यदि आपकी एसिंक विधि वास्तव में एसिंक नहीं है (मूल I/O लाभ प्रदान करती है) तो यह वास्तव में केवल ओवरहेड जोड़ती है। दूसरे शब्दों में, यह किसी भी स्केलेबिलिटी लाभ प्रदान नहीं करेगा।

मैं बस यह चाहूंगा कि बाकी समुदाय ने इस समस्या का सामना कैसे किया है।

+2

'async' और' await' एक अवरुद्ध विधि को एक गैर-अवरुद्ध विधि में बदलने के लिए केवल अमूर्त हैं। इंटरफ़ेस को बदलने के बिना, आप अपने कोड में कहीं भी ऐसा कर सकते हैं, जब तक आप इंटरफ़ेस विधि को हमेशा असीमित नहीं करना चाहते हैं। –

+1

यदि आपके पास संपूर्ण कॉल स्टैक में कार्य नहीं है, तो इसे कभी भी अतुल्यकालिक रूप से नहीं कहा जाएगा। तो आपको हमेशा एक कार्य वापस करने के लिए इंटरफ़ेस में रखना होगा। –

+1

ऐसा नहीं है जो मैंने कहा था। मैंने जो कहा था, क्या आप किसी भी विधि को 'async' और' await' का उपयोग कर एसिंक्रोनस में बदल सकते हैं, जिसमें आपके इंटरफेस पर पहले से मौजूद उन अवरोधन विधियों में से कोई भी शामिल है। एक विधि ''मूल विधि पर वापसी प्रकार की आवश्यकता नहीं है। यह निश्चित रूप से, आपके सभी इंटरफ़ेस विधियों को उनके 'async' समकक्षों के साथ प्रतिस्थापित करने के लिए एक पूरी तरह से मान्य चीज़ है, लेकिन इसकी आवश्यकता नहीं है। –

उत्तर

14

अपनी स्थिति में, मैं अपने इंटरफेस अतुल्यकालिक बनाने की सलाह देते:

public interface IMyInterface 
{ 
    Task<TMyResult> GetDataAsync(); 
} 

तुल्यकालिक तरीकों के लिए, आप Task.FromResult लौट सकते हैं:

public class MyImplementation : IMyInterface 
{ 
    public Task<TMyResult> GetDataAsync() 
    { 
    TMyResult ret = ...; 
    return Task.FromResult(ret); 
    } 
} 

अतुल्यकालिक तरीकों निश्चित रूप से async हो सकता है और await उपयोग कर सकते हैं।

कार्यान्वयन विवरण के संबंध में, मैं "हाँ और नहीं" कहूंगा। ;) यह इस संबंध में IDisposable के समान है। तर्कसंगत रूप से, यह इस अर्थ में एक कार्यान्वयन विस्तार है कि इससे कोई फर्क नहीं पड़ता कि इसे किस तरह कार्यान्वित किया गया है। यह इस अर्थ में एक कार्यान्वयन विस्तार है कि कॉलिंग कोड को इसे अलग-अलग संभालने की आवश्यकता है। इसलिए मैं सहमत हूं कि - तर्कसंगत - यह एक कार्यान्वयन विस्तार है, लेकिन .NET प्लेटफ़ॉर्म इस तरह के इलाज के लिए पर्याप्त रूप से उन्नत नहीं है।

वैकल्पिक रूप से, अगर आप इस तरह यह सोच सकते हैं (जो मैं आमतौर पर स्पष्टीकरण देना है): async वास्तविक क्रियान्वयन विस्तार है, और जब आप T के बजाय Task<T> लौटने के लिए, आप एक इंटरफेस जहां कार्यान्वयन मई तय कर रहे हैं असीमित हो।

मैं एक series of blog posts "बड़े में" async साथ डिजाइनिंग का पता है कि (जैसे कि, OOP के साथ में async फिटिंग बजाय यह कार्यक्षम होने के लिए अनुमति देता है)। मैं कुछ सामान्य समस्याओं जैसे कि एसिंक्रोनस प्रारंभिकरण और आईओसी को संबोधित करता हूं। यह सिर्फ एक व्यक्ति की राय है, लेकिन मुझे इस तरह की समस्याओं के लिए किसी अन्य संसाधन से अवगत नहीं है।

पीएस आपको MVC4 में अब AsyncController से प्राप्त करने की आवश्यकता नहीं है। डिफ़ॉल्ट नियंत्रक हैंडलर स्वचालित रूप से उनके रिटर्न प्रकार (Task या Task<T>) द्वारा async विधियों का पता लगाएगा।

+0

ब्लॉग पोस्ट की आपकी श्रृंखला का लिंक टूटा हुआ प्रतीत होता है। क्या आप अपडेट कर सकते हैं? – fourpastmidnight

+0

कोई बात नहीं, क्रोम बेवकूफ था और लिंक को सही ढंग से "अनुवाद" नहीं किया था। पोस्ट करने का शुक्रिया। – fourpastmidnight

+0

दरअसल, लिंक टूट गया था; मैंने इस साल की शुरुआत में प्रदाताओं को बदल दिया। यह अभी तय है, धन्यवाद! –

1

कार्य एक रिसाव अमूर्त है। यदि आप आईओ पूर्णता बंदरगाह धागे के उपयोग का लाभ उठाना चाहते हैं, तो आपको अपने रिपॉजिटरीज़ से अपने नियंत्रकों तक सभी तरह से कार्य वापस करना होगा।

हालांकि पूरे कॉल स्टैक रिटर्न Task<T> को स्केलेबिलिटी में सुधार हो सकता है, यह आपके आवेदन में जटिलता की एक अतिरिक्त परत जोड़ता है। इससे रखरखाव, टेस्टेबिलिटी में बाधा आती है और कोड के बारे में तर्क करना मुश्किल हो जाता है। Asynchronous code will always be harder than synchronous code

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

+2

मैं जटिलता की अतिरिक्त परत से असहमत हूं। रखरखाव, टेस्टेबिलिटी, और कोड तर्क 'async'/'await' के साथ सीधा है (एक बार जब आप उन्हें समझते हैं)। –

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