2017-06-26 13 views
5

answers to this question के माध्यम से पढ़ना मुझे इस बात के बारे में सोचने के लिए प्रेरित करता है कि प्रतीक्षा कार्य जब फंसे हुए कार्य को फेंकता है। क्या सभी "क्लाइंट" अपवाद का पालन करते हैं? मैं मानता हूं कि मैं यहां कुछ चीजों को भ्रमित कर सकता हूं; यही कारण है कि मैं स्पष्टीकरण के लिए पूछ रहा हूं।क्या होता है जब एकाधिक समांतर धागे एक ही कार्य उदाहरण का इंतजार करते हैं जो तब फेंकता है?

मैं एक ठोस परिदृश्य पेश होगा ... चलो कहते हैं कि मैं लंबे समय से चल Task उदाहरणों में से एक वैश्विक संग्रह, ग्राहकों द्वारा शुरू के साथ एक सर्वर चला रहे हैं। एक या अधिक कार्यों को शुरू करने के बाद, एक ग्राहक अपनी प्रगति पर सवाल उठा सकता है और परिणाम उपलब्ध होने पर परिणाम प्राप्त कर सकता है, साथ ही साथ होने वाली त्रुटियों के साथ भी।

कार्य स्वयं बहुत अलग व्यापार-विशिष्ट चीजें कर सकते हैं - आम तौर पर, कोई भी दो समान नहीं होते हैं। हालांकि, यदि कोई ग्राहक पहले से शुरू होने के समान कार्य शुरू करने का प्रयास करता है, तो सर्वर को इसे पहचानना चाहिए और दूसरे क्लाइंट को एक नई प्रतिलिपि बनाने के बजाय मौजूदा कार्य में "संलग्न" करना चाहिए।

अब, हर बार किसी भी ग्राहक कार्य में रुचि है की स्थिति प्रश्नों, इन पंक्तियों के साथ कुछ करता है:

var timeout = Task.Delay(numberOfSecondsUntilClientsPatienceRunsOut); 
try 
{ 
    var result = await Task.WhenAny(timeout, task); 
    if (result == timeout) 
    { 
     // SNIP: No result is available yet. Just report the progress so far. 
    } 

    // SNIP: Report the result. 
} 
catch (Exception e) 
{ 
    // SNIP: Report the error. 
} 

संक्षेप में, यह काम कुछ उचित समय क्या यह पहली बार कर रहा है खत्म करने के लिए देता है , फिर चल रही प्रगति की रिपोर्ट करने के लिए वापस आ जाता है। इसका मतलब है कि समय की एक संभावित महत्वपूर्ण खिड़की है जिसमें कई ग्राहक एक ही कार्य को विफल कर सकते हैं।

मेरा प्रश्न है: यदि कार्य इस विंडो के दौरान फेंकने के लिए होता है, तो क्या सभी ग्राहकों द्वारा अपवाद (और संभाला जाता है) है?

+0

"लौटाया गया कार्य पूरा हो जाएगा जब किसी भी आपूर्ति किए गए कार्यों को पूरा कर लिया जाएगा। लौटाया कार्य हमेशा 'RanToCompletion' राज्य में समाप्त होगा, इसके परिणाम 'सेट' के साथ पहले कार्य में सेट होगा। यह सच है भले ही पहले रद्द या फॉल्ट राज्य में समाप्त होने के लिए कार्य। " यदि 'टास्क 'दोष, और पूरा हो गया है, और एक से अधिक ग्राहक इस निर्माण के माध्यम से इसका इंतजार कर रहे हैं, तो उन सभी को दोषपूर्ण कार्य दिखाई देगा। यदि वे 'कार्य' (नतीजे 'नहीं' के परिणाम का निरीक्षण करने का प्रयास करते हैं तो उनमें से सभी को अपवाद मिलेगा। यह "पहले आओ, पहले मिलता है" सौदा नहीं है। –

+0

इस आगे सरल करने के लिए: यदि आप का इंतजार है 'Task.Run ((=)> नया अपवाद फेंक (DateTime.Now.Ticks.ToString()))' एक पंक्ति (अपवाद संचालक के साथ) में कई बार, आप एक मिल जाएगा प्रत्येक बार अपवाद, एक ही समय के टिकट के साथ (कार्य को साबित करने के लिए कई बार निष्पादित नहीं किया जा रहा है)। एक दोषपूर्ण कार्य आपको पसंद के रूप में कई अपवादों का उत्पादन कर सकता है। –

+2

दिलचस्प सवाल है, लेकिन अपने आप को परीक्षण करने के लिए पर्याप्त आसान है। – spender

उत्तर

4

Task.WhenAny खुद को फेंक नहीं देगा। प्रति the documentation:

लौटा कार्य पूरा हो जाएगा जब किसी भी आपूर्ति किए गए कार्यों में पूरा हो जाएगा। लौटाया कार्य हमेशा RanToCompletion राज्य में समाप्त होगा, जिसके परिणाम को पूरा करने के पहले कार्य में सेट किया जाएगा। यह है, भले ही पूरा करने वाला पहला कार्य Canceled या Faulted स्थिति में समाप्त हो गया हो।

आप वापस या तो timeout या task मिल जाएगा।

यदि परिणाम task है, और आप इसका इंतजार कर रहे हैं (या Task.Result प्राप्त करें), और task में गलती हुई है, तो वह फेंक देगा। इससे कोई फ़र्क नहीं पड़ता कि कितने कॉलर ऐसा करते हैं, या जब वे ऐसा करते हैं - एक दोषपूर्ण कार्य का नतीजा हमेशा प्राप्त करने का प्रयास करता है। इसे प्रदर्शित करने के लिए सरल कोड:

var t = Task.Run(() => throw new Exception(DateTime.Now.Ticks.ToString())); 
try { 
    await t; 
} catch (Exception e) { 
    Console.WriteLine(e.Message); 
} 
await Task.Delay(1000); 
try { 
    await t; 
} catch (Exception e) { 
    Console.WriteLine(e.Message); 
} 

यह दो बार समान टाइमस्टैम्प प्रिंट करेगा। कार्य केवल एक बार चलता है, और केवल एक परिणाम होता है, जो हर बार जब आप इसे प्राप्त करने का प्रयास करते हैं तो अपवाद उत्पन्न करता है। यदि आप चाहें तो आप विभिन्न धागे या समांतर कॉल में मिश्रण कर सकते हैं, इससे परिणाम नहीं बदला जाता है।

ध्यान दें कि एक टाइमआउट के मामले में, अभी भी दौड़ की स्थिति की मूल संभावना है: दो अलग-अलग कार्य/थ्रेड, दोनों एक ही कार्य का इंतजार कर रहे हैं, await Task.WhenAny(timeout, task) पर अलग-अलग परिणाम प्राप्त कर सकते हैं, इस आधार पर कि वे किस कार्य को देखते हैं पहले पूरा करें। दूसरे शब्दों में, भले ही await Task.WhenAny(timeout, task) == timeout, task.WhenAny() के बीच किसी भी बिंदु पर अभी भी गलती हो सकती है और यह तय कर रहा है कि अंततः आपके पास वापस आ रहा है।इसकी अपेक्षा की जा सकती है, और आपके कोड को इसे संभालना चाहिए (प्रतीक्षा के अगले दौर पर, .WhenAny() तुरंत दोषपूर्ण कार्य के साथ वापस आ जाएगा)।

+0

किसी भी downvoters करने के लिए: एक टिप्पणी समझा छोड़ दें क्यों जवाब गलत है, या यह कैसे सुधार किया जा सकता। –

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

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