2012-08-10 8 views
88

तो मुझे हाल ही में बताया गया था कि मैं अपना उपयोग कैसे कर रहा था। कार्य के लिए उनका उपयोग करने का उचित तरीका नहीं था। मुझे इंटरनेट पर इसका सबूत अभी तक नहीं मिला है इसलिए मैं आपको लोगों से पूछूंगा और देख सकता हूं कि जवाब क्या है। यहाँ .ContinueWith मैं कैसे उपयोग का एक उदाहरण है:prevTask.Wait() को जारी रखने के लिए अनुशंसित किया गया है (कार्य पुस्तकालय से)?

public Task DoSomething() 
{ 
    return Task.Factory.StartNew(() => 
    { 
     Console.WriteLine("Step 1"); 
    }) 
    .ContinueWith((prevTask) => 
    { 
     Console.WriteLine("Step 2"); 
    }) 
    .ContinueWith((prevTask) => 
    { 
     Console.WriteLine("Step 3"); 
    }); 
} 

अब मुझे पता है यह एक सरल उदाहरण है और यह बहुत तेजी से चलाया जाएगा, लेकिन अभी प्रत्येक कार्य कुछ लंबे समय तक आपरेशन करता है मान लेते हैं। तो, मुझे जो बताया गया था वह है। कॉन्टिन्यू के साथ, आपको prevTask.Wait() कहना होगा; अन्यथा आप पिछले कार्य खत्म होने से पहले काम कर सकते हैं। क्या यह भी संभव है? मुझे लगता है कि मेरा दूसरा & तीसरा कार्य केवल एक बार उनके पिछले कार्य खत्म होने के बाद ही चलाया जाएगा।

मैं क्या बताया गया था कि कैसे कोड लिखने के लिए:

public Task DoSomething() 
{ 
    return Task.Factory.StartNew(() => 
    { 
     Console.WriteLine("Step 1"); 
    }) 
    .ContinueWith((prevTask) => 
    { 
     prevTask.Wait(); 
     Console.WriteLine("Step 2"); 
    }) 
    .ContinueWith((prevTask) => 
    { 
     prevTask.Wait(); 
     Console.WriteLine("Step 3"); 
    }); 
} 
+2

स्टार्टन्यू का उपयोग न करें http://blog.stephencleary.com/2013/08/startnew-is-dangerous.html –

उत्तर

113

Ehhh .... मैं वर्तमान कुछ उत्तर लगता है कि कुछ याद कर रहे हैं: अपवादों के साथ क्या होता है?

एकमात्र कारण आप निरंतरता में Wait पर कॉल करेंगे, निरंतरता में पूर्ववर्ती से संभावित अपवाद का पालन करना होगा। यदि आप Task<T> के मामले में Result तक पहुंच गए हैं और यदि आपने मैन्युअल रूप से Exception संपत्ति का उपयोग किया है, तो वही अवलोकन होगा। सचमुच, मैं Wait पर कॉल नहीं करता या Result तक पहुंच नहीं पाता क्योंकि अगर कोई अपवाद है तो आप इसे फिर से उठाने की कीमत का भुगतान करेंगे जो अनावश्यक ओवरहेड है। इसके बजाय आप पूर्व Task से IsFaulted संपत्ति की जांच कर सकते हैं। वैकल्पिक रूप से आप कई भाई-बहनों की निरंतरताओं पर चेन करके फोर्क किए गए वर्कफ़्लो बना सकते हैं जो केवल TaskContinuationOptions.OnlyOnRanToCompletion और TaskContinuationOptions.OnlyOnFaulted के साथ सफलता या विफलता के आधार पर आग लगती हैं।

अब, निरंतरता में पूर्ववर्ती के अपवाद का पालन करना आवश्यक नहीं है, लेकिन हो सकता है कि आप "वर्कफ़्लो" विफल होने पर अपने वर्कफ़्लो को आगे बढ़ना न चाहें। उस स्थिति में: को अपने ContinueWith कॉलों को निर्दिष्ट करने से निरंतर तर्क को कभी भी फायरिंग से रोका जा सकेगा।

ध्यान रखें कि, यदि आपकी अपनी निरंतरता अपवाद का पालन नहीं करती है, तो वह व्यक्ति जो इस समग्र वर्कफ़्लो को पूरा करने के लिए इंतजार कर रहा है वह इसे देखने के लिए होगा। या तो Task अपस्ट्रीम पर Wait आईएनजी हैं या यह पूर्ण होने पर जानने के लिए अपनी निरंतरता पर निपटा है। यदि यह उत्तरार्द्ध है, तो उनके निरंतरता को उपर्युक्त अवलोकन तर्क का उपयोग करने की आवश्यकता होगी।

+2

आखिरकार कोई सही जवाब देता है। @ Travyguy9 कृपया इस @DrewMarsh उत्तर को पढ़ें और 'टास्ककंटिन्यूशनऑप्शन' – Jasper

+0

अच्छी कॉल के बारे में और पढ़ें। धन्यवाद! – Travyguy9

+2

ग्रेट उत्तर, मैं यह देख रहा था कि "ध्यान रखें कि, यदि आपकी खुद की निरंतरता अपवाद का पालन नहीं करती है, तो वह व्यक्ति जो इस समग्र वर्कफ़्लो को पूरा करने के लिए इंतजार कर रहा है, वह इसे देखेगा।" _ एक प्रश्न हालांकि, जब आपका कार्य इंतजार नहीं किया जाता है, तो डिफ़ॉल्ट वेटर कौन है? (इसका उत्तर नहीं मिला) –

20

आप इसे सही ढंग से उपयोग कर रहे हैं।

एक निरंतरता है कि एसिंक्रोनस रूप से निष्पादित जब लक्ष्य कार्य को पूरा करता बनाता है।

स्रोत: Task.ContinueWith Method (Action as MSDN)

हर Task.ContinueWith मंगलाचरण में prevTask.Wait() कॉल करने के लिए होने अनावश्यक तर्क को दोहराने के लिए एक अजीब तरह से की तरह लगता है - कुछ कर रही है अर्थात् क्योंकि आप वास्तव में समझ में नहीं आता "सुपर duper यकीन है कि" होने का क्या कोड का एक निश्चित बिट करता है। एक ArgumentNullException फेंकने के लिए बस एक नल की जांच की तरह, जहां भी इसे फेंक दिया गया होगा।

तो, नहीं, जो भी आपको बताता है कि यह गलत है और शायद यह नहीं समझता कि Task.ContinueWith क्यों मौजूद है।

5

MSDN से Task.Continuewith

द लौटे वर्तमान कार्य पूरा कर लिया है जब तक कार्य निष्पादन के लिए निर्धारित नहीं किया जाएगा। यदि निरंतरता के माध्यम से निर्दिष्ट मानदंडों को पूरा नहीं किया गया है, तो निरंतर कार्य निर्धारित होने के बजाय रद्द कर दिया जाएगा।

मुझे लगता है कि जिस तरह से आप इसे पहले उदाहरण में काम करने की उम्मीद करते हैं वह सही तरीका है।

16

किसने आपको बताया था?

MSDN का हवाला देते हुए:

एक निरंतरता है कि एसिंक्रोनस रूप से निष्पादित जब लक्ष्य कार्य को पूरा करता बनाता है।

इसके अलावा, हो सकता है क्या के प्रयोजन जारी यह पिछले कार्य के लिए इंतजार नहीं कर रहा था, तो साथ पूरा हो जाने की?

तुम भी यह अपने आप द्वारा परीक्षण कर सकते हैं:

Task.Factory.StartNew(() => 
    { 
     Console.WriteLine("Step 1"); 
     Thread.Sleep(2000); 
    }) 
    .ContinueWith((prevTask) => 
    { 
     Console.WriteLine("I waited step 1 to be completed!"); 
    }) 
    .ContinueWith((prevTask) => 
    { 
     Console.WriteLine("Step 3"); 
    }); 
0

एक्सेस करना Task.Result आप वास्तव में task.wait

+0

हां। हम प्रतीक्षा() विधि से बच सकते हैं। लेकिन यह केवल परिणाम कार्यों के साथ काम करता है, उदा। कार्य

+0

डाउनवॉटेड क्योंकि यह वास्तविक प्रश्न को संबोधित नहीं करता है। यह कुछ मूल्य जोड़ता है, लेकिन एक टिप्पणी होना चाहिए। – Sinaesthetic

1

के समान तर्क रही हैं तुम भी Task.Factory.StartNew के बजाय Task.Run उपयोग करने पर विचार कर सकते हैं।

स्टीफन क्लेरी के blog post और स्टीफन टब के post that he references मतभेदों की व्याख्या करते हैं। this answer में भी एक चर्चा है।

+3

डाउनवॉटेड क्योंकि यह वास्तविक प्रश्न को संबोधित नहीं करता है। यह कुछ मूल्य जोड़ता है, लेकिन एक टिप्पणी होना चाहिए। – Sinaesthetic

0

मैं दोहराने वाले लोगों को दोहरा दूंगा, prevTask.Wait()अनावश्यक है।

अधिक उदाहरणों के लिए कोई Chaining Tasks using Continuation Tasks पर जा सकता है, फिर भी माइक्रोसॉफ्ट द्वारा अच्छे उदाहरणों के साथ एक और लिंक।

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