टास्क <int> int कैसे बनता है?


116

हमारे पास यह तरीका है:

async Task<int> AccessTheWebAsync()
{ 
    HttpClient client = new HttpClient();

   Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

   // You can do work here that doesn't rely on the string from GetStringAsync.
   DoIndependentWork();

   string urlContents = await getStringTask;
   //The thing is that this returns an int to a method that has a return type of Task<int>
   return urlContents.Length;
}

क्या एक अंतर्निहित रूपांतरण Task<int>और के बीच होता है int? यदि नहीं, तो क्या हो रहा है? इसे काम करने के लिए कैसे लागू किया जाता है?


1
पढ़ते रहिए । मुझे लगता है कि कंपाइलर asyncकीवर्ड के आधार पर इसका ध्यान रखता है ।
डी स्टैनले

1
@ फ़्रीमैन, इस महान विवरण को देखें: stackoverflow.com/a/4047607/280758
qehgt

जवाबों:


171

क्या टास्क <> और इंट के बीच एक अंतर्निहित रूपांतरण होता है?

नहीं। यह कैसे async/ awaitकाम करता है का सिर्फ एक हिस्सा है ।

asyncवापसी के प्रकार के लिए घोषित की गई कोई भी विधि :

  • void (यदि संभव हो तो बचें)
  • Task (पूरा होने / विफलता की अधिसूचना से परे कोई परिणाम नहीं)
  • Task<T>( Tएक async तरीके से तार्किक परिणाम के लिए )

कंपाइलर सभी उचित रैपिंग करता है। मुद्दा यह है कि आप एसिंक्रोनस रूप से लौट रहे हैं urlContents.Length- आप विधि को केवल वापस नहीं ला सकते हैं int, क्योंकि वास्तविक विधि वापस आ जाएगी जब यह पहली awaitअभिव्यक्ति को हिट करता है जो पहले से ही पूरा नहीं हुआ है। तो इसके बजाय, यह एक रिटर्न देता है Task<int>जो पूरा हो जाएगा जब एसिंक्स विधि खुद पूरी हो जाएगी।

ध्यान दें कि awaitइसके विपरीत - यह एक मूल्य को उजागर करता Task<T>है T, जो कि यह रेखा कैसे काम करती है:

string urlContents = await getStringTask;

... लेकिन निश्चित रूप से यह इसे अतुल्यकालिक रूप से उजागर करता है, जबकि बस का उपयोग Resultकरना तब तक अवरुद्ध होता है जब तक कि कार्य पूरा नहीं हो जाता। ( awaitअन्य प्रकारों को अनचाहा कर सकते हैं जो प्रतीक्षा करने योग्य पैटर्न को लागू करते हैं, लेकिन Task<T>क्या आप अक्सर उपयोग करने की संभावना रखते हैं।)

यह दोहरी रैपिंग / अल्ट्रापॉपिंग है जो async को इतना कंपोज करने योग्य बनाता है। उदाहरण के लिए, मैं एक और async विधि लिख सकता हूं, जो आपका कॉल करता है और परिणाम को दोगुना करता है:

public async Task<int> AccessTheWebAndDoubleAsync()
{
    var task = AccessTheWebAsync();
    int result = await task;
    return result * 2;
}

(या बस return await AccessTheWebAsync() * 2;निश्चित रूप से)


3
किसी भी विवरण के लिए पेशकश की जा सकती है कि यह हुड के नीचे कैसे काम करता है, बस उत्सुक है।
फ्रीमैन

8
+1 हमेशा की तरह अच्छा जवाब। और आप उन्हें लिखने में बहुत तेज क्यों हैं ?!
फेलिक्स के।

9
+1: बस में देखना शुरू कर दिया async/ awaitऔर मुझे यह बेहद गैर-सहज लगता है। IMO, वहाँ पर कोई कीवर्ड या समान होना चाहिए returnयह स्पष्ट है, जैसे बनाने के लिए return async result;(एक ही तरीके से कि await result"unwraps" Tसे Tast<T>)।
dav_i

2
@JonSkeet लेकिन यह बिना मतलब नहीं है await- के साथ T foo = someTaskT;आपको मिल चाहते हैं "परोक्ष प्रकार कनवर्ट नहीं कर सकता Task<T>करने के लिए T" - उसी तरह मैं तर्क है कि इसे और अधिक समझ बनाने होता उलटा (में रैपिंग के लिए एक कीवर्ड के लिए में Task<T>)। मैं फुल निकालने के लिए हूं, लेकिन इस मामले में मुझे लगता है कि यह asyncतरीकों के भीतर एक अनावश्यक अवरोधन प्रदान करता है । (स्पष्ट रूप से यह बिंदु मूट है क्योंकि जो शक्तियां पहले से ही बोली / कोड की गई हैं!)
dav_i

2
@dav_i: असाइनमेंट का कोई मतलब नहीं है, लेकिन बाकी काम करता है। और ऐसे मामले हैं जहां पूरे बयान से समझ में आएगा - हालांकि यह उपयोगी नहीं हो सकता है। यह देखते हुए कि विधि पहले से ही घोषित है async, मुझे लगता है कि यह पर्याप्त है।
जॉन स्कीट

18

टास्क को इंट में कनवर्ट करने की आवश्यकता नहीं है। बस टास्क रिजल्ट का उपयोग करें।

int taskResult = AccessTheWebAndDouble().Result;

public async Task<int> AccessTheWebAndDouble()
{
    int task = AccessTheWeb();
    return task;
}

यदि उपलब्ध है तो यह मान लौटाएगा अन्यथा यह 0 पर लौटेगा।


20
यह वह नहीं है जो मैंने पूछा।
फ्रीमैन

16
इस सवाल का जवाब नहीं है। लेकिन इससे भी महत्वपूर्ण बात यह है कि यह बहुत बुरी सलाह है । आपको लगभग कभी भी उपयोग नहीं करना चाहिए Result; यह गतिरोध पैदा कर सकता है! उदाहरण के लिए इस वर्कफ़्लो पर विचार करें: (1) एक नोट लिखें जो "लॉन को म्याऊ" कहता है। (2) लॉन के पिघलने की प्रतीक्षा करें (3) एक सैंडविच खाएं, (4) नोट पर जो कुछ भी कहें, उसे करें "। उस वर्कफ़्लो के साथ, आप कभी भी सैंडविच नहीं खाते हैं या लॉन को म्याऊ नहीं करते हैं, क्योंकि चरण 2 एक समकालिक प्रतीक्षा है। भविष्य में आप जो कुछ करेंगे उस पर । लेकिन आप यहाँ जो वर्कफ़्लो
बता

@EricLippert: अपना उदाहरण स्पष्ट न करें। क्या आप यह बता सकते हैं कि जब इंतजार नहीं होगा तो परिणाम कैसे गतिरोध ला सकते हैं?
चरिथज

3
प्रतीक्षा का अर्थ है कि परिणाम के लिए प्रतीक्षा करते समय कुछ करना और परिणाम को गणना करने के लिए कुछ करना शामिल हो सकता है। लेकिन तुल्यकालिक प्रतीक्षा करते समय आप कुछ भी नहीं करते हैं जिसका अर्थ है कि आप कार्य को होने से रोक सकते हैं।
एरिक लिपपर्ट

1
@EricLippert। क्या यह एक ही मुद्दा होगा? 'Task.Run () (> = AccessTheWebAndDouble ()) परिणाम;)
चरिथज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.