हाल ही में मैं C # 5.0 के अद्भुत async-wait पैटर्न के लिए पर्याप्त प्रतीत नहीं हो सकता । मेरे पूरे जीवन में आप कहां रहे?
मैं बिल्कुल सरल वाक्य रचना से रोमांचित हूं, लेकिन मुझे एक छोटी सी कठिनाई हो रही है। मेरी समस्या यह है कि async फ़ंक्शंस में नियमित फ़ंक्शंस से बिल्कुल अलग घोषणा है। चूंकि केवल async फ़ंक्शंस अन्य async फ़ंक्शंस पर प्रतीक्षा कर सकते हैं, जब मैं कुछ पुराने ब्लॉकिंग कोड को async पोर्ट करने का प्रयास कर रहा हूं, तो मुझे उन फ़ंक्शन का एक डोमिनोज़ प्रभाव पड़ रहा है जिन्हें मुझे कनवर्ट करना है।
लोग इसे ज़ोंबी इन्फ़ेक्शन बता रहे हैं । जब async आपके कोड में काटता है, तो यह बड़ा और बड़ा होता रहेगा। पोर्टिंग प्रक्रिया मुश्किल नहीं है, यह सिर्फ async
घोषणा में फेंक रहा है और रिटर्न वैल्यू के साथ लपेट रहा है Task<>
। लेकिन पुराने सिंक्रोनस कोड को पोर्ट करते समय बार-बार ऐसा करना कष्टप्रद होता है।
मुझे लगता है कि यह बहुत अधिक स्वाभाविक होगा यदि दोनों प्रकार के फ़ंक्शन (async और सादे पुराने सिंक) में एक समान सिंटैक्स था। यदि ऐसा होता, तो पोर्टिंग शून्य प्रयास लेती और मैं दो रूपों के बीच दर्द रहित रूप से स्विच कर सकता था।
मुझे लगता है कि अगर हम इन नियमों का पालन करते हैं तो यह काम कर सकता है:
Async फ़ंक्शन को
async
अब घोषणा की आवश्यकता नहीं होगी । उनकी वापसी के प्रकार में लिपटे नहीं होना चाहिएTask<>
। संकलक अपने द्वारा संकलन के दौरान एक async फ़ंक्शन की पहचान करेगा और आवश्यकतानुसार टास्क <> रैपिंग करेगा।कोई और अधिक आग और भूल कॉल async कार्यों के लिए। यदि आप एक async फ़ंक्शन को कॉल करना चाहते हैं, तो आपको उस पर इंतजार करना होगा। मैं शायद ही किसी भी तरह से आग और भूल जाता हूं, और पागल दौड़ की स्थिति या गतिरोध के सभी उदाहरण हमेशा उन पर आधारित लगते हैं। मुझे लगता है कि वे बहुत भ्रामक हैं और "स्पर्श से बाहर" के साथ समकालिक मानसिकता का हम लाभ उठाने की कोशिश करते हैं।
यदि आप वास्तव में आग और भूल के बिना नहीं रह सकते हैं, तो इसके लिए विशेष वाक्यविन्यास होगा। किसी भी मामले में, मैं उस सरल एकीकृत सिंटैक्स का हिस्सा नहीं बनूंगा जिसके बारे में मैं बात कर रहा हूं।
एक एसिंक्रोनस कॉल को निरूपित करने के लिए आपको एकमात्र कीवर्ड की आवश्यकता होती है
await
। यदि आपको इंतजार है, तो कॉल अतुल्यकालिक है। यदि आप नहीं करते हैं, तो कॉल सादा पुराना तुल्यकालिक है (याद रखें, हमारे पास आग और भूल नहीं है)।कंपाइलर स्वचालित रूप से async फ़ंक्शन की पहचान करेगा (क्योंकि उनके पास अब कोई विशेष घोषणा नहीं है)। नियम 4 यह करने के लिए बहुत सरल बनाता है - यदि किसी फ़ंक्शन के
await
अंदर कॉल है, तो यह async है।
क्या यह काम कर सकता है? या क्या मैं कुछ न कुछ भूल रहा हूं? यह एकीकृत सिंटैक्स बहुत अधिक तरल पदार्थ है और पूरी तरह से ज़ोंबी संक्रमण को हल कर सकता है।
कुछ उदाहरण:
// assume this is an async function (has await calls inside)
int CalcRemoteBalanceAsync() { ... }
// assume this is a regular sync function (has no await calls inside)
int CalcRemoteBalance() { ... }
// now let's try all combinations and see what they do:
// this is the common synchronous case - it will block
int b1 = CalcRemoteBalance();
// this is the common asynchronous case - it will not block
int b2 = await CalcRemoteBalanceAsync();
// choosing to call an asynchronous function in a synchronous manner - it will block
// this syntax was used previously for async fire-and-forget, but now it's just synchronous
int b3 = CalcRemoteBalanceAsync();
// strange combination - it will block since it's calling a synchronous function
// it should probably show a compilation warning though
int b4 = await CalcRemoteBalance();
नोट: यह SO में एक दिलचस्प संबंधित चर्चा का एक निरंतरता है
await
तुरंत नहीं है । आप कुछ ऐसा कर सकते हैं var task = FooAsync(); Bar(); await task;
। मैं आपके प्रस्ताव में यह कैसे करूंगा?
async
। मुझे लगता है कि इसका एक बड़ा फायदा यह है कि: async
- await
यह आपको आसानी से अतुल्यकालिक संचालन बनाने की अनुमति देता है (और न केवल सबसे सरल "स्टार्ट ए में, ए की प्रतीक्षा करें, बी से शुरू करें, बी के लिए प्रतीक्षा करें")। और इस उद्देश्य के लिए पहले से ही विशेष वाक्यविन्यास है: इसे कहा जाता है await
।