2017-05-04 9 views
10

एसिंक विधि को लागू करने/समर्थित या अमान्य ऑपरेशन के रूप में चिह्नित करने का सही तरीका क्या नहीं है। सादगी के लिए मैं उदाहरणों में केवल NotImplementedException का उपयोग करूंगा, लेकिन प्रश्न NotSupportedException और InvalidOperationException पर भी लागू होता है।कार्यान्वित/समर्थित/अमान्य ऑपरेशन async विधि

एक सिंक तरह से एक होगा अपवाद सरल फेंक:

public override void X() { 
    throw new NotImplementedException(); 
} 

क्या async दुनिया में इस कोड के बराबर हो सकता है?

/* 1 */ public override Task XAsync() { 
    throw new NotImplementedException(); 
} 

या

/* 2 */ public override Task XAsync() { 
    return Task.FromException(new NotImplementedException()); 
} 

इन तरीकों की जटिलताओं क्या हैं? क्या कोई बेहतर तरीका है?


से बचने के लिए "नहीं, आप एक विधि की जरूरत नहीं है यहाँ async होने के लिए"/"यह async नहीं कर रहा है" मैं कहूँगा कि विधि कुछ इंटरफ़ेस या अमूर्त वर्ग लागू करता है।


कुछ तरीकों जो मैं नहीं पर विचार कर रहा हूँ:

/* 3 */ public async override Task XAsync() { // here is an CS1998 warning 
    throw new NotImplementedException(); 
} 

संकलक would just generate the useless state machine, जो शब्दार्थ 2

/* 4 */ public async override Task XAsync() { 
    await Task.Yield(); 
    throw new NotImplementedException(); 
} 

यह the same 3 के रूप में है के बराबर है, लेकिन इंतजार के साथ जोड़ा कार्य पर। युवा();

+3

अच्छा सवाल। पहला विकल्प अपवाद फेंकता है जब विधि लागू की जाती है, दूसरा परिणाम जब प्रतीक्षा की जाती है। मेरे पास पहले विकल्प के लिए एक छोटी वरीयता है, क्योंकि यह "जल्दी विफल रहता है", लेकिन मुझे आश्चर्य है कि विशेषज्ञों को क्या कहना होगा। – Heinzi

+0

शायद यह मदद करता है: http: // stackoverflow।कॉम/ए/13254787/31679 9 –

+0

हाँ, @ फ़ेलिपऑरियन ने देखा कि, धन्यवाद – hazzik

उत्तर

3

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

तो परिणाम सभी विकल्पों के लिए समान है: तत्काल फेंक दें या एक कार्य जो पहले से ही अपवाद के साथ पूरा हो चुका है (केवल तभी व्यवहार करता है जब आप तुरंत कॉल का इंतजार करते हैं) या async विधि को चिह्नित करें (जो आपको उम्मीद करेगा await कॉल करें लेकिन चलो इसे पूर्णता के लिए जोड़ें)।

मैं तुरंत फेंकने के लिए जाना चाहते हैं, क्योंकि एक टास्क का संकेत हो सकता है कि आप "काम शुरू कर दिया है" और फोन करने वाले एक टास्क का इंतजार करने के लिए तो अगर फोन करने वाले वास्तव में जब की परवाह नहीं है की आवश्यकता नहीं है लौटने आपका Task पूरा करता है (इसमें वापसी मूल्य भी नहीं है), तथ्य यह है कि विधि लागू नहीं की जाएगी।

+0

जबकि मैं इस पर इच्छुक हूं ... यह बीसी का निर्माण नहीं करेगा, अगर आप – micahhoover

+0

का इंतजार नहीं कर रहे हैं तो आप y कार्य को वापस करने की विधि में फेंक दें, 'async' कीवर्ड का उपयोग करके अपनी विधि को परिभाषित न करें। –

4

मैं एक अंग पर बाहर जाने जा रहा हूं और कहता हूं "इससे कोई फर्क नहीं पड़ता।"

Boneheaded exceptions सीधे (throw) फेंक दिया जा सकता है या लौटा कार्य (Task.FromException) पर रखा जा सकता है। चूंकि वे अपर्याप्त अपवाद हैं, इसलिए उन्हें कभी भी पकड़ा नहीं जाना चाहिए, इसलिए इससे कोई फर्क नहीं पड़ता कि उन्हें कहां फेंक दिया गया है।

2

अपनी टिप्पणी में, आप ने लिखा है: कुशल द्वारा लिखित सुप्रसिद्ध पुस्तकालयों:

हम NHibernate :)

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

ऐसे लोग हैं जो await Task.WhenAll(a(), b(), c()) जैसे कोड की उम्मीद करते हैं, भले ही एसिंक्रोनस ऑपरेशंस में से कोई एक विफल हो, मैं कहूंगा कि आपका पहला विकल्प भी एक विकल्प नहीं होना चाहिए। यदि b() एक अपवाद को सिंक्रनाइज़ करता है, तो a() का लौटा कार्य अनदेखा हो जाता है, और c() कॉल नहीं किया जाता है।

मैं स्टीफन क्लेरी के जवाब से सहमत हूं कि NotImplementedException है, क्योंकि वह इसे रखता है, एक हड्डी का अपवाद जहां इससे कोई फर्क नहीं पड़ता, क्योंकि इसे किसी भी तरह से उत्पादन कोड में कभी खत्म नहीं होना चाहिए। हालांकि, आप लिखते हैं:

प्रश्न NotSupportedException और InvalidOperationException पर भी लागू होता है।

ये आवश्यक रूप से अपर्याप्त अपवाद नहीं हैं। ये उत्पादन कोड में समाप्त हो सकता है।

आपका दूसरा विकल्प उस समस्या से बचाता है।

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

मैं भी

public async override Task XAsync() { 
    throw new NotImplementedException(); 
} 

जो आपको एक राज्य मशीन बनाने के साथ जुड़े भूमि के ऊपर की वजह से खारिज कर दिया पर विचार सुझाव दिया। मुझे लगता है कि इसे छोड़ने का यह वैध कारण नहीं है। यह वह कोड है जहां प्रदर्शन प्रासंगिक नहीं है, यह वह कोड है जो केवल त्रुटि मामलों को संभालता है। मैंने सुझाव दिया क्योंकि आम तौर पर, मैं async/await का उपयोग सीधे कार्यों में हेरफेर करने के पक्ष में हूं, क्योंकि मूर्खतापूर्ण गलतियों को पकड़ना इतना आसान है, क्योंकि विकास के समय में बचाया गया समय काफी हद तक पर्याप्त है।

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

अन्य दो में से, उम्मीद है कि कमियों के विवरण आपको एक सुविज्ञ निर्णय लेने में मदद करते हैं।

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