एक ही तरीके के भीतर सिंक और एसिंक्स विधियों का कुशल मिश्रण?


11

ठीक है, यह अजीब लगता है, लेकिन कोड बहुत सरल है और स्थिति को अच्छी तरह से समझाता है।

public virtual async Task RemoveFromRoleAsync(AzureTableUser user, string role)
{
    AssertNotDisposed();
    var roles = await GetRolesForUser(user);
    roles.Roles = RemoveRoles(roles.Roles, role);
    await Run(TableOperation.Replace(roles));
}

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

मैं अब और अधिक बार इस पैटर्न का सामना कर रहा हूं जो कि मैं async/ awaitअधिक का उपयोग कर रहा हूं । पैटर्न में घटनाओं की निम्नलिखित श्रृंखला शामिल है:

  1. एक प्रारंभिक कॉल का इंतजार करें जो मुझे कुछ जानकारी देता है जिस पर मुझे काम करने की आवश्यकता है
  2. उस जानकारी पर सिंक्रोनाइज़ करें
  3. अंतिम कॉल की प्रतीक्षा करें जो अद्यतन किए गए कार्य को सहेजता है

उपरोक्त कोड ब्लॉक आम तौर पर इन तरीकों को संभालने के बारे में है। मैं awaitपहला कॉल करता हूं, जो मुझे करना है क्योंकि यह एसिंक्रोनस है। अगला, मैं वह काम करता हूं जो मुझे करने की आवश्यकता है जो IO या संसाधन बाध्य नहीं है, और इसलिए यह async नहीं है। अंत में, मैं अपना काम बचा लेता asyncहूं जो एक कॉल भी है , और कार्गो-पंथ से बाहर awaitहै।

लेकिन क्या इस पैटर्न को संभालने का यह सबसे कुशल / सही तरीका है? ऐसा लगता है कि मैं awaitअंतिम कॉल को छोड़ सकता हूं , लेकिन अगर यह विफल रहता है तो क्या होगा? और क्या मुझे मूल कॉल के साथ अपने तुल्यकालिक काम को चेन करने के लिए एक Taskविधि का उपयोग करना चाहिए ContinueWith? मैं अभी एक बिंदु पर हूं जहां मुझे यकीन नहीं है कि मैं इसे सही तरीके से संभाल रहा हूं।

उदाहरण में कोड को देखते हुए , क्या इस async / सिंक / async विधि कॉल श्रृंखला को संभालने का एक बेहतर तरीका है?


कोड मुझे जितना संभव हो उतना छोटा और समझ में आता है। कुछ भी मैं अनावश्यक जटिलता का परिचय देने के बारे में सोच सकता हूं।
बृहस्पतिवार

@ आशिक: क्या मुझे अपने आखिरी कॉल का इंतजार करना चाहिए? अगर मैं नहीं करता और क्या होता, तो क्या होता? क्या यह वर्तमान में कोई भिन्न होगा?
बंद Ripped

जवाबों:


3

हां, मुझे लगता है कि यह करने का सही तरीका है।

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

मैं नहीं देखता ContinueWith()कि यहाँ कैसे या कुछ भी इस तरह की मदद करेगा । आप इसका उपयोग करने से बचने के लिए कर सकते हैं await, लेकिन यह आपके कोड को अधिक जटिल और कम पठनीय बना देगा। और वह पूरा बिंदु है await: लेखन अतुल्यकालिक कोड को सरल बनाना, जब निरंतरता का उपयोग करके तुलना की जाती है।


0

इस पैटर्न को संभालने का तरीका यह सुनिश्चित करना है कि सभी I / O अतुल्यकालिक हैं। सिंक्रोनस I / O विधियाँ वर्तमान थ्रेड को ब्लॉक करने का कारण बनती हैं जबकि यह I / O गंतव्य (नेटवर्क, फ़ाइल-सिस्टम, आदि) से प्रतिक्रिया की प्रतीक्षा करता है।

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

इसलिए, कंप्यूटिंग संसाधनों के सबसे कुशल उपयोग के लिए, यदि RemoveRolesकोई I / O है, तो यह बन जाना चाहिए await RemoveRolesAsyncऔर I / O विधियों को बुलाया RemoveRolesAsyncजाना भी async (और संभवतः प्रतीक्षित) होना चाहिए।

यदि प्रदर्शन आपकी अत्यधिक चिंता का विषय नहीं है, तो एक एसिंक्स थ्रेड पर कुछ सिंक्रोनस I / O करना ठीक है। हालांकि यह एक तकनीकी ऋण है। (इस मामले में, आप पहले async विधि के साथ कॉल कर सकते हैं ConfigureAwait, जहां कोड चल रहा है, इस पर निर्भर करता है।)

यहाँ सर्वोत्तम प्रथाओं पर अधिक गहराई से देखा गया है - https://msdn.microsoft.com/en-us/magazine/jj991977.aspx

यहाँ ASP.NET, वेबएपीआई, आदि की तरह अलग अलग वातावरण में ConfigureAwait के व्यवहार के बारे कुछ नोट कर रहे हैं - /programming/13489065/best-practice-to-call-configureawait-for-all-server-side -code


2
आपको कभी भी आग नहीं लगानी चाहिए और टास्क को भूल जाना चाहिए। सभी कार्यों का इंतजार किया जाना चाहिए। यदि आप टास्क का इंतजार नहीं करते हैं, और टास्क को एक ऐसी स्थिति में कचरा-संग्रहित किया जाता है, जहां अपवाद "अनबॉस्स्ड" है, तो यह रन-टाइम में अनब्सॉर्स्डटैस्क अपवाद को जन्म देगा और फ्रेमवर्क संस्करण के आधार पर आपके एप्लिकेशन को क्रैश कर सकता है।
त्रिनको
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.