वास्तव में, async / प्रतीक्षा यह जादुई नहीं है। पूरा विषय काफी व्यापक है लेकिन आपके प्रश्न के त्वरित और अभी तक पूर्ण उत्तर के लिए मुझे लगता है कि हम प्रबंधित कर सकते हैं।
आइए विंडोज फॉर्म एप्लिकेशन में एक साधारण बटन क्लिक ईवेंट से निपटें:
public async void button1_Click(object sender, EventArgs e)
{
Console.WriteLine("before awaiting");
await GetSomethingAsync();
Console.WriteLine("after awaiting");
}
मैं स्पष्ट रूप से इस बारे में बात नहीं करने जा रहा हूं कि यह GetSomethingAsync
अभी के लिए जो भी लौट रहा है। मान लें कि यह कुछ ऐसा है जो 2 सेकंड के बाद पूरा होगा।
एक पारंपरिक, गैर-अतुल्यकालिक, दुनिया में, आपका बटन क्लिक इवेंट हैंडलर कुछ इस तरह दिखाई देगा:
public void button1_Click(object sender, EventArgs e)
{
Console.WriteLine("before waiting");
DoSomethingThatTakes2Seconds();
Console.WriteLine("after waiting");
}
जब आप फॉर्म में बटन पर क्लिक करते हैं, तो एप्लिकेशन लगभग 2 सेकंड के लिए स्थिर हो जाएगा, जबकि हम इस विधि के पूरा होने की प्रतीक्षा करते हैं। क्या होता है कि "संदेश पंप", मूल रूप से एक लूप, अवरुद्ध है।
यह लूप लगातार विंडोज़ पूछता है "क्या किसी ने कुछ किया है, जैसे माउस को स्थानांतरित किया, कुछ पर क्लिक किया? क्या मुझे कुछ पुनरावृत्ति करने की आवश्यकता है? यदि हां, तो मुझे बताएं!" और फिर उस "कुछ" को संसाधित करता है। इस लूप को एक संदेश मिला कि उपयोगकर्ता ने "बटन 1" (या विंडोज से बराबर प्रकार का संदेश) पर क्लिक किया, और button1_Click
ऊपर दी गई विधि को समाप्त कर दिया । इस विधि के वापस आने तक, यह लूप अब प्रतीक्षा में अटका हुआ है। इसमें 2 सेकंड का समय लगता है और इस दौरान, कोई भी संदेश संसाधित नहीं किया जा रहा है।
खिड़कियों से निपटने वाली अधिकांश चीजें संदेशों का उपयोग करके की जाती हैं, जिसका अर्थ है कि यदि संदेश लूप पंप संदेशों को रोक देता है, यहां तक कि सिर्फ एक सेकंड के लिए भी, यह उपयोगकर्ता द्वारा जल्दी से ध्यान देने योग्य है। उदाहरण के लिए, यदि आप अपने स्वयं के प्रोग्राम के शीर्ष पर नोटपैड या किसी अन्य प्रोग्राम को स्थानांतरित करते हैं, और फिर फिर से दूर जाते हैं, तो आपके प्रोग्राम को पेंट संदेशों की एक झड़ी भेजी जाती है, जो यह इंगित करता है कि विंडो का कौन सा क्षेत्र अब अचानक फिर से दिखाई देने लगा। यदि इन संदेशों को संसाधित करने वाला संदेश लूप किसी चीज़ की प्रतीक्षा कर रहा है, अवरुद्ध है, तो कोई पेंटिंग नहीं की जाती है।
इसलिए, यदि पहले उदाहरण में, async/await
नए धागे नहीं बनाए जाते हैं, तो यह कैसे करता है?
खैर, क्या होता है कि आपकी विधि दो में विभाजित है। यह उन चीजों के व्यापक विषय प्रकारों में से एक है, इसलिए मैं बहुत अधिक विस्तार में नहीं जाऊंगा, लेकिन यह कहने के लिए पर्याप्त है कि विधि इन दो भागों में विभाजित है:
await
कॉल करने के लिए , सहित सभी कोडGetSomethingAsync
- निम्नलिखित सभी कोड
await
उदाहरण:
code... code... code... await X(); ... code... code... code...
पुन: व्यवस्थित:
code... code... code... var x = X(); await X; code... code... code...
^ ^ ^ ^
+---- portion 1 -------------------+ +---- portion 2 ------+
मूल रूप से विधि इस तरह से निष्पादित होती है:
- यह सब कुछ निष्पादित करता है
await
यह GetSomethingAsync
विधि को कॉल करता है, जो अपनी बात करता है, और कुछ ऐसा करता है जो भविष्य में 2 सेकंड पूरा करेगा
अब तक हम अभी भी मूल कॉल के अंदर हैं बटन1_ क्लिक करें, मुख्य लूप पर हो रहा है, जिसे मैसेज लूप कहा जाता है। यदि कोड को await
बहुत समय लगता है, तो UI अभी भी स्थिर रहेगा। हमारे उदाहरण में, इतना नहीं
await
कुछ चतुर कंपाइलर जादू के साथ कीवर्ड क्या करता है, यह है कि यह मूल रूप से "ठीक है, आप जानते हैं कि क्या है, मैं बस बटन पर क्लिक करके इवेंट हैंडलर से यहां लौटने जा रहा हूं। जब आप (जैसे हम, बात हम ' पुन: प्रतीक्षा) पूरा करने के लिए चारों ओर हो, मुझे बताएं क्योंकि मेरे पास अभी भी कुछ कोड निष्पादित करने के लिए बचा है "।
वास्तव में यह SynchronizationContext क्लास को यह बताने देगा कि ऐसा किया गया है, जो कि वास्तविक सिंक्रनाइज़ेशन संदर्भ के आधार पर होता है, जो अभी चल रहा है, निष्पादन के लिए कतार में खड़ा होगा। Windows प्रपत्र प्रोग्राम में उपयोग किया जाने वाला संदर्भ वर्ग कतार का उपयोग करके इसे पंक्तिबद्ध करेगा कि संदेश लूप पंप कर रहा है।
इसलिए यह संदेश लूप पर वापस लौटता है, जो अब संदेशों को पंप करना जारी रखने के लिए स्वतंत्र है, जैसे खिड़की को हिलाना, उसका आकार बदलना, या अन्य बटन पर क्लिक करना।
उपयोगकर्ता के लिए, यूआई अब फिर से उत्तरदायी है, अन्य बटन क्लिकों को संसाधित करना, आकार बदलना और सबसे महत्वपूर्ण बात, फिर से करना , इसलिए यह फ्रीज करने के लिए प्रकट नहीं होता है।
- 2 सेकंड बाद, जिस चीज़ का हम पूरा होने का इंतज़ार कर रहे हैं और अब जो होता है, वह यह है (ठीक है, सिंक्रोनाइज़ेशन का संदर्भ) एक संदेश को कतार में रखता है जिसे संदेश लूप देख रहा है, "अरे, मुझे कुछ और कोड मिला है" आप निष्पादित करने के लिए ", और यह कोड प्रतीक्षा के बाद का सभी कोड है ।
- जब संदेश लूप उस संदेश को प्राप्त हो जाता है, तो यह मूल रूप से उस विधि को "पुनः दर्ज" करेगा, जहां उसने इसे छोड़ दिया था, बस बाद में
await
और बाकी विधि को निष्पादित करना जारी रखें। ध्यान दें कि इस कोड को मैसेज लूप से फिर से कॉल किया जाता है ताकि यदि यह कोड async/await
ठीक से उपयोग किए बिना कुछ लंबा करने के लिए होता है , तो यह मैसेज लूप को फिर से ब्लॉक कर देगा
वहाँ कई चलती भागों हुड के नीचे यहाँ इसलिए यहाँ कर रहे हैं अधिक जानकारी के लिए कुछ लिंक कर रहे हैं, मैं कहना है "आप इसे की आवश्यकता चाहिए" जा रहा था, लेकिन इस विषय है काफी व्यापक है और यह पता करने के लिए काफी महत्वपूर्ण है उन भागों चलती के कुछ । वास्तव में आप समझ रहे हैं कि async / प्रतीक्षा अभी भी एक लीक अवधारणा है। अंतर्निहित सीमाओं और समस्याओं में से कुछ अभी भी आसपास के कोड में लीक हो जाती हैं, और यदि वे नहीं करते हैं, तो आप आमतौर पर एक एप्लिकेशन को डिबग करने के लिए समाप्त होते हैं जो प्रतीत होता है कि बिना किसी अच्छे कारण के बेतरतीब ढंग से टूट जाता है।
ठीक है, तो क्या होगा यदि GetSomethingAsync
2 सेकंड में पूरा होने वाला एक धागा ऊपर घूम जाएगा? हां, तो जाहिर है कि नाटक में एक नया सूत्र है। यह धागा, तथापि, नहीं है क्योंकि इस विधि का async सत्ता का ऐसा इसलिए है क्योंकि इस विधि के प्रोग्रामर एक धागा एसिंक्रोनस कोड लागू करने के लिए चुना है। लगभग सभी अतुल्यकालिक I / O एक धागे का उपयोग नहीं करते हैं, वे विभिन्न चीजों का उपयोग करते हैं। async/await
अपने आप से नए धागे नहीं उधेड़ते, लेकिन जाहिर है "जिन चीजों का हम इंतजार करते हैं" उन्हें धागे का उपयोग करके लागू किया जा सकता है।
.NET में बहुत सी चीजें हैं जो जरूरी नहीं कि एक धागा को अपने आप में स्पिन करें लेकिन अभी भी अतुल्यकालिक हैं:
- वेब अनुरोध (और कई अन्य नेटवर्क से संबंधित चीजें जो समय लेती हैं)
- अतुल्यकालिक फ़ाइल पढ़ना और लिखना
- और कई और अधिक, एक अच्छा संकेत है, तो सवाल में वर्ग / इंटरफेस का नाम दिया है तरीकों है
SomethingSomethingAsync
या BeginSomething
और EndSomething
और वहाँ एक है IAsyncResult
शामिल।
आमतौर पर ये चीजें हुड के नीचे एक धागे का उपयोग नहीं करती हैं।
ठीक है, तो आप "व्यापक विषय सामान" में से कुछ चाहते हैं?
खैर, हमारे बटन क्लिक के बारे में रोज़लिन से पूछें :
रोजलिन की कोशिश करो
मैं यहाँ पूरी तरह से उत्पन्न वर्ग में लिंक नहीं करने जा रहा हूँ, लेकिन यह बहुत सुंदर सामान है।