2010-08-11 9 views
22

मैं वर्तमान में नए System.Threading.Tasks .net में पाया कार्यक्षमता का उपयोग एक नया कार्यान्वयन के साथ कुछ घर पके हुए कार्य कार्यक्षमता की जगह रहा 4.कैसे सूचना है कि एक System.Threading.Tasks.Task पूरा कर लिया है पाने के लिए

हालांकि मुझे थोड़ा सा मुद्दा है, और हालांकि मैं कुछ समाधानों के बारे में सोच सकता हूं, मुझे कुछ सलाह चाहिए जो आम तौर पर ऐसा करने का सबसे अच्छा तरीका है, और यदि मुझे कहीं चाल चल रही है।

मुझे एक कार्य शुरू करने में सक्षम होने के लिए मनमाने ढंग से प्रक्रिया की आवश्यकता है, लेकिन फिर कार्य को समाप्त करने के लिए आगे बढ़ें और प्रतीक्षा न करें। कोई समस्या नहीं है, लेकिन जब मुझे किसी कार्य के परिणामस्वरूप कुछ करने की ज़रूरत है तो मुझे यह सुनिश्चित करने का सबसे अच्छा तरीका नहीं है।

मेरे द्वारा देखे गए सभी उदाहरण या तो कार्य पर प्रतीक्षा करें() कार्य पर परिणाम पैरामीटर को पूरा या संदर्भित करते हैं। ये दोनों धागे को अवरुद्ध करेंगे जो कार्य शुरू कर चुके हैं, जो मैं नहीं चाहता हूं।

कुछ समाधान मैं के बारे में सोचा है

  1. एक नया धागा बनाने और उस पर काम शुरू करते हैं, तो नया थ्रेड ब्लॉक करने के लिए प्रतीक्षा करें() या .Result का उपयोग करें और परिणाम फोन करने वाले के लिए वापस सिंक किसी भी तरह, संभवतः कार्यों के लिए मतदान के साथ पूर्ण पैरामीटर है।

  2. एक 'अधिसूचित पूरा करें' कार्य है जिसे मैं उस कार्य को पूरा करने के बाद शुरू कर सकता हूं जिसे मैं चलाने के लिए चाहता हूं जो तब एक स्थिर घटना या कुछ उठाता है।

  3. कार्य के इनपुट में एक प्रतिनिधि को पास करें और यह बताएं कि कार्य समाप्त हो गया है।

मुझे लगता है कि कर सकते हैं या पक्ष-विपक्ष उन सभी को है, लेकिन मैं विशेष रूप से पर काम शुरू करने के लिए स्पष्ट रूप से एक नया धागा बनाने के लिए होने का विचार पसंद नहीं है जब का उपयोग करने के उद्देश्यों में से एक पहली जगह में कार्य वर्ग सीधे थ्रेड उपयोग से दूर होना है।

सबसे अच्छा तरीका के बारे में कोई विचार? क्या मुझे कुछ आसान याद आ रही है? एक 'पूर्ण' घटना के लिए पूछने के लिए बहुत अधिक होगा :)? (यही कारण है कि एक नहीं है सुनिश्चित करें कि इसका कोई खास कारण है!)

+0

जिज्ञासा से, पृष्ठभूमिवर्कर का उपयोग क्यों नहीं करें? इसमें कार्य पूरा करने के साथ-साथ रद्दीकरण अधिसूचना भी है। – Robaticus

+1

'BackgroundWorker' अब अब जरूरी नहीं है कि' टास्क 'हमारे साथ है। बीजीडब्ल्यू को 'सिंक्रनाइज़ेशन कॉन्टेक्स्ट' की आवश्यकता होती है, जो 'टास्क' के साथ वैकल्पिक है (अधिक समांतरता को सक्षम करता है)। –

उत्तर

26

मैं संदिग्ध आप Task.ContinueWith (या Task<T>.ContinueWith) के लिए देख रहे हैं। ये मूल रूप से कहते हैं, "जब आप यह कार्य पूरा कर लेंगे, तो इस क्रिया को निष्पादित करें।" हालांकि, ऐसे कई विकल्प हैं जिन्हें आप अधिक नियंत्रण लेने के लिए निर्दिष्ट कर सकते हैं।

एमएसडीएन "How to: Chain Multiple Tasks With Continuations" और "Continuation Tasks" में इस पर बहुत अधिक जानकारी देता है।

+0

हां मैं इसे समझता हूं, लेकिन यह कार्य शुरू करने की समस्या को हल नहीं करता है जब कार्य शुरू करने वाले धागे पर टास्क।() और इसलिए अवरुद्ध) को कॉल किए बिना कार्य का अनुक्रम समाप्त हो गया है। एक दृष्टिकोण जिस पर मैंने सोचा था (उपर्युक्त) कार्य का उपयोग करना था। कंटिन्यू एक कार्य को श्रृंखलाबद्ध करने के लिए जो इच्छुक पार्टियां सब्सक्राइब कर सकती हैं। यह मूल कार्य परमाणु रखेगा। –

+1

@bwilliams: क्यों न केवल कार्य का पर्दाफाश करें, और इच्छुक पार्टियां 'कार्य' कॉल कर सकते हैं? मैं यह नहीं देखता कि यह कार्य * पूरा होने पर जानने की समस्या को हल नहीं करता है ... यह एक गैर-अवरुद्ध कॉल है जो कहता है, "यह समाप्त होने पर मुझे वापस कॉल करें।" –

+1

(या कार्य को स्वयं प्रकट करने के बजाय, आप अपनी खुद की विधि प्रदान कर सकते हैं जो तब केवल 'जारी रखें' को आंतरिक रूप से कॉल करता है। यह वही बात है, वास्तव में।) –

4

आप task continuation लागू कर सकते हैं।

वैकल्पिक रूप से, TaskIAsyncResult लागू करता है, तो आप standard approaches for that interface (अवरुद्ध, मतदान, या उसके WaitHandle पर इंतजार कर) का उपयोग कर सकते हैं।

+0

कार्य निरंतरता विषय के लिए कृपया जॉन स्कीट के पोस्ट के तहत मेरी टिप्पणी देखें। अवरुद्ध करना और मतदान करना मुझे इस विचार को पसंद नहीं है क्योंकि इसका मतलब यह होगा कि मूल थ्रेड को रखने के लिए एक और धागा शुरू करना है जो कार्य को उत्तरदायी बना देता है। मैंने देखा कि मैं वेटहैंडल का उपयोग कर सकता हूं, लेकिन दस्तावेज़ीकरण का कहना है कि पसंदीदा तरीका Task.Wait() का उपयोग करना है। उस ने कहा, जैसा कि मैं चाहता हूं कि वह नहीं करता है, वेटहैंडल मेरे लिए सबसे अच्छा है –

4

आधुनिक सी # में, अब किसी को स्पष्ट रूप से ContinueWith() पर कॉल करने की आवश्यकता नहीं है। मूल स्वीकृत उत्तर का एक विकल्प केवल async विधि बनाना होगा जो awaitTask प्रश्न में है, और Task पूर्ण होने पर जो कुछ भी चाहता है वह करता है।

उदाहरण के लिए, मान लीजिए कि Task पूर्ण होने पर आप TaskCompleted नामक एक ईवेंट को उठाना चाहते हैं। आप एक विधि लिखेंगे जैसे:

async Task RaiseEventWhenTaskCompleted(Task task) 
{ 
    await task; 
    TaskCompleted?.Invoke(this, EventArgs.Empty); 
} 

प्रतीक्षा "पंजीकरण" करने के लिए, बस उपरोक्त विधि को कॉल करें। वांछित के रूप में अपवाद हैंडलिंग जोड़ें, या तो ऊपर की विधि में, या कुछ कोड में जो अंततः उपरोक्त विधि द्वारा Task को वापस देखेगा।

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

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