मैं क्या समझ से, इंतजार कीवर्ड कोड प्रवाह को निलंबित कर देगा फ़ंक्शन तक
ठीक है, हाँ और नहीं।
- हां, क्योंकि कोड प्रवाह एक अर्थ में बंद हो जाता है।
- नहीं, क्योंकि इस कोड प्रवाह को निष्पादित करने वाला धागा अवरुद्ध नहीं होता है। (सिंक्रोनस कॉल
client.GetString()
धागे को अवरुद्ध करेगा)।
वास्तव में, यह इसकी कॉलिंग विधि पर वापस आ जाएगा। यह समझने के लिए कि इसका क्या मतलब है इसकी कॉलिंग विधि पर लौटने से, आप एक और सी # कंपाइलर जादू - yield return
कथन के बारे में पढ़ सकते हैं। जहां yield return
बयान के बाद कोड केवल निष्पादित करेंगे के बाद MoveNext()
प्रगणक पर कहा जाता है -
yield return
साथ
इटरेटर ब्लॉक एक राज्य मशीन में विधि टूट जाएगा। (this और this देखें)।
अब, async/await
तंत्र इसी तरह की राज्य मशीन पर भी आधारित है (हालांकि, यह yield return
राज्य मशीन से कहीं अधिक जटिल है)।
मामलों को आसान बनाने के लिए, की सुविधा देता है एक सरल async विधि पर विचार:
public async Task MyMethodAsync()
{
// code block 1 - code before await
// await stateement
var r = await SomeAwaitableMethodAsync();
// code block 2 - code after await
}
- आप
async
पहचानकर्ता के साथ एक विधि निशान जब आप एक राज्य मशीन में विधि को तोड़ने के लिए संकलक बता और है कि आप करने जा रहे हैं इस विधि के अंदर await
।
- मान लें कि कोड
Thread1
पर थ्रेड पर चल रहा है और आपका कोड इस MyMethodAsync()
पर कॉल करता है। फिर code block 1
एक ही थ्रेड पर सिंक्रनाइज़ रूप से चलेंगे।
SomeAwaitableMethodAsync()
को सिंक्रनाइज़ भी कहा जाएगा - लेकिन मान लें कि विधि एक नया एसिंक्रोनस ऑपरेशन शुरू करती है और Task
देता है।
- यह तब होता है जब
await
तस्वीर में आता है। यह कोड कॉल को अपने कॉलर पर वापस कर देगा और थ्रेड Thread1
कॉलर्स कोड चलाने के लिए स्वतंत्र है। कॉलिंग विधि में क्या होता है इस पर निर्भर करता है कि कॉलिंग विधि await
एस MyMethodAsync()
पर है या कुछ और करता है - लेकिन महत्वपूर्ण बात Thread1
अवरुद्ध नहीं है।
- अब प्रतीक्षा का जादू बाकी है - जब
SomeAwaitableMethodAsync()
द्वारा लौटाया गया कार्य अंततः पूरा हो जाता है, तो code block 2
अनुसूचित चलाने के लिए है।
async/await
कार्य समांतर पुस्तकालय पर बनाया गया है - इसलिए, टीपीएल पर शेड्यूलिंग किया गया है।
- अब यह बात यह है कि यह
code block 2
उसी धागे Thread1
पर निर्धारित नहीं किया जा सकता है जब तक कि यह थ्रेड एफ़िनिटी (जैसे WPF/WinForms UI थ्रेड) के साथ सक्रिय SynchronizationContext
सक्रिय न हो। await
SynchronizationContext
जागरूक है, इसलिए, code block 2
SynchronizationContext
, यदि कोई हो, तो MyMethodAsync()
पर कॉल किया गया था। यदि कोई सक्रिय SynchronizationContext
नहीं था, तो सभी संभावनाओं के साथ, code block 2
कुछ अलग थ्रेड पर चलाएगा।
अन्त में, मैं कहना है कि चूंकि async/await
संकलक द्वारा बनाई गई राज्य मशीन, yield return
की तरह पर आधारित है, यह कमियों के कुछ शेयरों - उदाहरण के लिए, आप नहीं await
एक finally
अंदर ब्लॉक कर सकते हैं।
मुझे आशा है कि यह आपके संदेहों को साफ़ करेगा।
यह मुख्य निष्पादन संदर्भ/धागा को अवरुद्ध नहीं करता है, इसलिए उदा। UI को जमे हुए नहीं किया जाएगा (यूआई का उपयोग करने वाले एप्लिकेशन में)। –
लेकिन यह मुख्य रूप से इसलिए है क्योंकि विधि स्वयं ही 'async' है, है ना? इसका मतलब यह नहीं होगा कि जब तक यह सामानों में व्यस्त हो, तब तक कॉलिंग थ्रेड जारी रह सकता है? – Rijk
नहीं, async की आवश्यकता है ताकि यह प्रतीक्षा कर सके। सभी जादू प्रतीक्षा कॉल पर खुश हैं। – ghord