2014-07-08 16 views
64

मैं वर्तमान में पढ़ रहा हूँ "सी # कुकबुक में संगामिति" स्टीफन Cleary से, और मैं निम्नलिखित तकनीक देखा:कार्य के समान कार्य पूरा होने की प्रतीक्षा करें। परिणाम?

var completedTask = await Task.WhenAny(downloadTask, timeoutTask); 
if (completedTask == timeoutTask) 
    return null; 
return await downloadTask; 

downloadTask httpclient.GetStringAsync के लिए एक कॉल है, और timeoutTask टास्क को क्रियान्वित कर रहा है। विलंब।

अगर यह समय-समय पर नहीं हुआ, तो डाउनलोडटास्क पहले ही पूरा हो चुका है। DownloadTask.Result को वापस करने के बजाए दूसरा इंतजार करना जरूरी क्यों है, यह देखते हुए कि कार्य पहले ही पूरा हो चुका है?

+3

यहां कुछ संदर्भ गायब हैं, और जब तक कि लोगों को आसानी से पुस्तक तक पहुंच न हो, आपको इसे शामिल करने की आवश्यकता होगी। 'डाउनलोड टास्क' और 'टाइमआउट टास्क' क्या है? वो क्या करते हैं? –

+6

मुझे यहां सफल समापन के लिए वास्तविक जांच नहीं दिखाई दे रही है। कार्य को बहुत अच्छी तरह से गलती की जा सकती है, और उस स्थिति में * 'await' के साथ' अपवाद डिस्पैचइन्फो 'के माध्यम से' परिणाम 'बनाम' अपवाद 'के साथ' पृथक अपवाद 'अलग-अलग होगा। स्टीफन टब के ".NET 4.5 में कार्य अपवाद हैंडलिंग" में अधिक विस्तार से चर्चा की गई: http://blogs.msdn.com/b/pfxteam/archive/2011/09/28/task-exception-handling-in-net-4 -5.aspx) –

+0

आपको इसे एक उत्तर @ KirillShlenskiy – Carsten

उत्तर

80

पहले से ही कुछ अच्छा जवाब/टिप्पणियों यहाँ हैं, लेकिन बस में झंकार के लिए ...

दो कारण मैं पसंद कर रहे हैं awaitResult से अधिक (या Wait)। पहला यह है कि त्रुटि प्रबंधन अलग है; awaitAggregateException में अपवाद को लपेटता नहीं है। आदर्श रूप से, एसिंक्रोनस कोड को कभी भी AggregateException से निपटना नहीं चाहिए, जब तक कि यह विशेष रूप से चाहता है।

दूसरा कारण थोड़ा और सूक्ष्म है। जैसा कि मैंने अपने ब्लॉग (और पुस्तक में), Result/Wait can cause deadlocks, और can cause even more subtle deadlocks when used in an async method पर वर्णन किया है। इसलिए, जब मैं कोड के माध्यम से पढ़ रहा हूं और मुझे Result या Wait दिखाई देता है, तो यह तत्काल चेतावनी ध्वज है। Result/Wait केवल तभी सही है यदि आप पूरी तरह से हैं कि कार्य पहले ही पूरा हो चुका है। न केवल एक नज़र में देखने के लिए मुश्किल है (असली दुनिया कोड में), लेकिन यह कोड परिवर्तनों के लिए और भी भंगुर है।

कहना है कि Result/Waitकभी नहीं इस्तेमाल किया जा चाहिए यही कारण है कि। मैं अपने दिशानिर्देशों में इन दिशानिर्देशों का पालन करता हूं:

  1. किसी एप्लिकेशन में असीमित कोड केवल await का उपयोग कर सकता है।
  2. असीमित उपयोगिता कोड (लाइब्रेरी में) कभी-कभी Result/Wait का उपयोग कर सकता है यदि कोड वास्तव में इसके लिए कॉल करता है। इस तरह के उपयोग शायद टिप्पणी होनी चाहिए।
  3. समांतर कार्य कोड Result और Wait का उपयोग कर सकते हैं।

ध्यान दें कि (1), मेरे हर जगह await का उपयोग करें और सामान्य नियम के अपवाद के रूप में अन्य मामलों के इलाज के लिए प्रवृत्ति दूर आम के मामले से है इसलिए।

+0

हमें हमारी परियोजनाओं में 'प्रतीक्षा' के बजाय 'परिणाम' का उपयोग करके डेडलॉक का सामना करना पड़ा। गड़बड़ वाले हिस्से में कोई संकलन त्रुटि नहीं है और आपका कोड थोड़ी देर के बाद flaky हो जाता है। –

+0

@ स्टीफन क्या आप कृपया मुझे समझाएंगे कि "आदर्श रूप से, एसिंक्रोनस कोड को कभी भी एग्रीगेट अपवाद से निपटना नहीं चाहिए, जब तक कि यह विशेष रूप से" – vcRobe

+1

@vcRobe "चाहता है क्योंकि 'प्रतीक्षा'' कुल एक्सेप्शन 'रैपर को रोकता है। 'एग्रीगेट एक्सेप्शन' समानांतर प्रोग्रामिंग के लिए डिज़ाइन किया गया था, असीमित प्रोग्रामिंग नहीं। –

7

यह समझ में आता है कि timeoutTaskTask.Delay का उत्पाद है, जो मुझे विश्वास है कि यह पुस्तक में क्या है।

Task.WhenAnyTask<Task> देता है, जहां आंतरिक कार्य उन लोगों में से एक है जिन्हें आपने तर्क के रूप में पारित किया है। यह इस तरह से फिर से लिखा जा सकता है:

Task<Task> anyTask = Task.WhenAny(downloadTask, timeoutTask); 
await anyTask; 
if (anyTask.Result == timeoutTask) 
    return null; 
return downloadTask.Result; 

या तो मामले में, क्योंकि downloadTask पहले ही पूरा हो गया है, वहाँ return await downloadTask और return downloadTask.Result के बीच एक बहुत ही मामूली अंतर है। यह है कि उत्तरार्द्ध AggregateException फेंक देगा जो किसी भी मूल अपवाद को लपेटता है, जैसा टिप्पणियों में @ किरीलशलेन्स्की द्वारा इंगित किया गया है। पूर्व मूल अपवाद को फिर से फेंक देगा।

किसी भी मामले में, जहां भी आप अपवादों को संभालते हैं, आपको त्रुटि के कारण प्राप्त करने के लिए AggregateException और इसके आंतरिक अपवादों की जांच करनी चाहिए।

संबंधित मुद्दे