समस्या यह है कि आप गैर-जेनेरिक Task
वर्ग का उपयोग कर रहे हैं , जिसका अर्थ परिणाम उत्पन्न करना नहीं है। तो जब आप Task
एक async डेलीगेट पास करने वाले उदाहरण को बनाते हैं :
Task myTask = new Task(async () =>
... प्रतिनिधि के रूप में माना जाता है async void
। एकasync void
नहीं है Task
, यह इंतजार नहीं किया जा सकता है, इसके अपवाद को संभाला नहीं जा सकता है, और यह हज़ारों सवालों का एक स्रोत है जो स्टैकऑवरफ़्लो और अन्य जगहों पर यहाँ निराश हैं। समाधान सामान्य Task<TResult>
वर्ग का उपयोग करना है, क्योंकि आप एक परिणाम वापस करना चाहते हैं, और परिणाम एक और है Task
। इसलिए आपको एक बनाना होगा Task<Task>
:
Task<Task> myTask = new Task<Task>(async () =>
अब जब आप Start
बाहरी Task<Task>
होंगे तो यह लगभग तुरंत पूरा हो जाएगा क्योंकि इसका काम सिर्फ आंतरिक निर्माण करना है Task
। फिर आपको भीतर की भी प्रतीक्षा करनी होगी Task
। यह इस प्रकार किया जा सकता है:
myTask.Start();
Task myInnerTask = await myTask;
await myInnerTask;
आपके पास दो विकल्प हैं। यदि आपको आंतरिक संदर्भ की स्पष्ट आवश्यकता नहीं है, Task
तो आप केवल Task<Task>
दो बार बाहरी प्रतीक्षा कर सकते हैं :
await await myTask;
... या आप बिल्ट-इन एक्सटेंशन विधि का उपयोग कर सकते हैं Unwrap
जो बाहरी और आंतरिक कार्यों को एक में जोड़ती है:
await myTask.Unwrap();
जब आप बहुत अधिक लोकप्रिय का उपयोग करते हैं तो यह अलिखित स्वचालित रूप से होता है Task.Run
विधि का जो गर्म कार्य बनाता है, इसलिए Unwrap
आजकल इसका उपयोग बहुत अधिक नहीं किया जाता है।
यदि आप यह तय करते हैं कि आपके async प्रतिनिधि को परिणाम वापस करना होगा, उदाहरण के लिए a string
, तो आपको myTask
चर को प्रकार का घोषित करना चाहिए Task<Task<string>>
।
नोट: मैं Task
ठंडे कार्यों को बनाने के लिए निर्माणकर्ताओं के उपयोग का समर्थन नहीं करता । एक अभ्यास के रूप में आम तौर पर उन कारणों के लिए, जिन्हें मैं वास्तव में नहीं जानता हूं, लेकिन शायद ही कभी इसका उपयोग किया जाता है, क्योंकि यह आश्चर्य से कोड के अन्य अनजान उपयोगकर्ताओं / अनुरक्षकों / समीक्षकों को पकड़ने की क्षमता रखता है।
सामान्य सलाह: हर बार सावधान रहें कि आप किसी विधि के तर्क के रूप में एक एसिंक्स प्रतिनिधि को आपूर्ति कर रहे हैं। इस विधि से आदर्श रूप से एक Func<Task>
तर्क की उम्मीद की जानी चाहिए (जिसका अर्थ है कि async प्रतिनिधियों को समझता है), या कम से कम एक Func<T>
तर्क (जिसका अर्थ है कि कम से कम उत्पन्न Task
को अनदेखा नहीं किया जाएगा)। दुर्भाग्यपूर्ण मामले में कि यह विधि एक को स्वीकार करती है Action
, आपके प्रतिनिधि को माना जाएगा async void
। यह शायद ही कभी आप चाहते हैं, अगर है।