C # 5.0 में async और नियमित कार्यों के बीच की रेखाओं को धुंधला करना


10

हाल ही में मैं C # 5.0 के अद्भुत async-wait पैटर्न के लिए पर्याप्त प्रतीत नहीं हो सकता । मेरे पूरे जीवन में आप कहां रहे?

मैं बिल्कुल सरल वाक्य रचना से रोमांचित हूं, लेकिन मुझे एक छोटी सी कठिनाई हो रही है। मेरी समस्या यह है कि async फ़ंक्शंस में नियमित फ़ंक्शंस से बिल्कुल अलग घोषणा है। चूंकि केवल async फ़ंक्शंस अन्य async फ़ंक्शंस पर प्रतीक्षा कर सकते हैं, जब मैं कुछ पुराने ब्लॉकिंग कोड को async पोर्ट करने का प्रयास कर रहा हूं, तो मुझे उन फ़ंक्शन का एक डोमिनोज़ प्रभाव पड़ रहा है जिन्हें मुझे कनवर्ट करना है।

लोग इसे ज़ोंबी इन्फ़ेक्शन बता रहे हैं । जब async आपके कोड में काटता है, तो यह बड़ा और बड़ा होता रहेगा। पोर्टिंग प्रक्रिया मुश्किल नहीं है, यह सिर्फ asyncघोषणा में फेंक रहा है और रिटर्न वैल्यू के साथ लपेट रहा है Task<>। लेकिन पुराने सिंक्रोनस कोड को पोर्ट करते समय बार-बार ऐसा करना कष्टप्रद होता है।

मुझे लगता है कि यह बहुत अधिक स्वाभाविक होगा यदि दोनों प्रकार के फ़ंक्शन (async और सादे पुराने सिंक) में एक समान सिंटैक्स था। यदि ऐसा होता, तो पोर्टिंग शून्य प्रयास लेती और मैं दो रूपों के बीच दर्द रहित रूप से स्विच कर सकता था।

मुझे लगता है कि अगर हम इन नियमों का पालन करते हैं तो यह काम कर सकता है:

  1. Async फ़ंक्शन को asyncअब घोषणा की आवश्यकता नहीं होगी । उनकी वापसी के प्रकार में लिपटे नहीं होना चाहिए Task<>। संकलक अपने द्वारा संकलन के दौरान एक async फ़ंक्शन की पहचान करेगा और आवश्यकतानुसार टास्क <> रैपिंग करेगा।

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

  3. यदि आप वास्तव में आग और भूल के बिना नहीं रह सकते हैं, तो इसके लिए विशेष वाक्यविन्यास होगा। किसी भी मामले में, मैं उस सरल एकीकृत सिंटैक्स का हिस्सा नहीं बनूंगा जिसके बारे में मैं बात कर रहा हूं।

  4. एक एसिंक्रोनस कॉल को निरूपित करने के लिए आपको एकमात्र कीवर्ड की आवश्यकता होती है await। यदि आपको इंतजार है, तो कॉल अतुल्यकालिक है। यदि आप नहीं करते हैं, तो कॉल सादा पुराना तुल्यकालिक है (याद रखें, हमारे पास आग और भूल नहीं है)।

  5. कंपाइलर स्वचालित रूप से 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 में एक दिलचस्प संबंधित चर्चा का एक निरंतरता है


3
आप हमेशा अपने अतुल्यकालिक संचालन पर इंतजार करते हैं? कृपया मुझे बताएं कि आप उन्हें फायर करने के तुरंत बाद ऐसा नहीं करते ...
जिमी हॉफ

1
इसके अलावा, async के बारे में महान चीजों में से एक यह है कि आपको awaitतुरंत नहीं है । आप कुछ ऐसा कर सकते हैं var task = FooAsync(); Bar(); await task;। मैं आपके प्रस्ताव में यह कैसे करूंगा?
svick

3
एसओ से चर्चा चल रही है जहां मेरा BFG-3000 है ...
रॉबर्ट हार्वे

2
@talkol आपको लगता है कि समानांतर प्रोग्रामिंग अश्लील है? यह एक दिलचस्प दृष्टिकोण है, कम से कम कहने के लिए, जब आप बात कर रहे हैं async। मुझे लगता है कि इसका एक बड़ा फायदा यह है कि: async- awaitयह आपको आसानी से अतुल्यकालिक संचालन बनाने की अनुमति देता है (और न केवल सबसे सरल "स्टार्ट ए में, ए की प्रतीक्षा करें, बी से शुरू करें, बी के लिए प्रतीक्षा करें")। और इस उद्देश्य के लिए पहले से ही विशेष वाक्यविन्यास है: इसे कहा जाता है await
svick

1
@svick हाहा, अब हम वहाँ गए हैं :) मुझे नहीं लगता कि समानांतर प्रचलन अश्लील है, लेकिन मुझे लगता है कि यह async-wait के साथ कर रहा है। एसिंक्स-वेट ब्लॉकिंग की कीमत का भुगतान किए बिना आपके समकालिक स्थिति को ध्यान में रखने के लिए सिंथेटिक शुगर है। यदि आप पहले से ही समानांतर में सोच रहे हैं, तो मैं आपसे एक अलग पैटर्न
टॉरोल

जवाबों:


9

आपके प्रश्न का उत्तर पहले ही आपके द्वारा लिंक किए गए SO प्रश्न में दिया गया है।

एसिंक्स / वेट का उद्देश्य कई उच्च विलंबता कार्यों वाली दुनिया में कोड लिखना आसान बनाना है। आपके संचालन का अधिकांश हिस्सा उच्च विलंबता नहीं है।

जब WinRT पहली बार बाहर आया, तो डिज़ाइनर बता रहे थे कि उन्होंने कैसे तय किया कि कौन से ऑपरेशन एसिंक्स होने वाले हैं। उन्होंने फैसला किया कि 50ms या उससे अधिक लेने वाली कोई भी चीज async होगी, और शेष विधियां साधारण, गैर-एसिंक्रोनस विधियां होंगी।

उन्हें अतुल्यकालिक बनाने के लिए कितने तरीकों को फिर से लिखना पड़ा? उनमें से लगभग 10 प्रतिशत। अन्य 90% प्रभावित नहीं हुए थे।

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


कृपया एसओ प्रश्न और इस एक के बीच पर्याप्त अंतर पर ध्यान दें। एसओ पूछते हैं कि सबकुछ क्यों नहीं बनाया जाए। यहाँ हम यह सुझाव नहीं देते हैं कि, हम सुझाव देते हैं कि 10% async करें, बस इसके लिए एक ही सिंटैक्स का उपयोग करें। एक निकट वाक्यविन्यास का उपयोग करने से यह फायदा होता है कि आप अधिक आसानी से बदल सकते हैं जो 10% async है, इन परिवर्तनों से प्रभावित डोमिनो प्रभाव के बिना
talkol

मैं थोड़ा अस्पष्ट हूं कि क्यों asyncज़ोंबी infestations का उत्पादन होगा। यहां तक ​​कि अगर एक विधि 10 अन्य तरीकों को बुलाती है, तो क्या आपके पास सिर्फ asyncशीर्ष-स्तर एक नहीं है?
रॉबर्ट हार्वे

6
मान लीजिए कि मेरे वर्तमान कोड का 100% सिंक है। अब मेरे पास एक एकल आंतरिक पत्ता-स्तरीय फ़ंक्शन है जो DB को प्रश्न करता है कि मैं async में बदलना चाहता हूं। अब इसे async बनाने के लिए मुझे इसके कॉलर को async, और इसके कॉलर को async होने की आवश्यकता है, और इसके बाद शीर्ष स्तर तक। बेशक, मैं उस मामले के बारे में बात कर रहा हूं, जहां पूरी श्रृंखला का इंतजार किया जा रहा है (कोड या पास रिटर्न
वैलेस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.