2010-08-06 6 views
11

मैं एक काम है कि कई बच्चे कार्यों की शुरूआत की है। (उदाहरण के लिए, कार्य ए बी, सी, डी, ई, एफ बनाता है)। मैं अनुरोध के अनुसार निर्धारित आइटम रद्द कर दिया गया था या नहीं, यह जांचने के लिए प्रत्येक 10 सेकंड में डेटाबेस को मतदान करने के लिए System.Threading.Timer भी बनाता है। यदि ऐसा होता है, तो यह CancellationTokenSource सेट करता है ताकि कार्य रद्द करना जानता हो। प्रत्येक उप-कार्य, इस मामले में बी, सी, डी, ई, एफ, उपयुक्त होने पर रद्द हो जाएगा (वे फाइलों के माध्यम से लूपिंग कर रहे हैं और उन्हें चारों ओर ले जा रहे हैं)।सिस्टम का निपटान कब करें। बच्चे के कार्यों के साथ थ्रेडिंग। कार्य?

Task के बाद से लागू करता IDisposable, मैं अगर यह एक अच्छा विचार catch ब्लॉक से फिर से Task.WaitAll कॉल करने के लिए, रद्द प्रचार करने के लिए इंतजार करना है जानना चाहते हैं। रद्द करने का अनुरोध कार्रवाई की जाएगी, वहीं उप-कार्य एक पाश के बीच में हो सकता है और रद्द नहीं कर सकते जब तक कि

पूरा करता है हालांकि, MSDN प्रति:

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

क्या मुझे सरणी में प्रत्येक कार्य पर Dispose() ठीक से कॉल करने के लिए अपने कार्य सरणी पर फिर से प्रतीक्षा करना चाहिए?

public class MyCancelObject 
{ 
    CancellationTokenSource Source { get;set;} 
    int DatabaseId { get;set;} 
} 

private void CheckTaskCancelled(object state) 
{ 
    MyCancelObject sourceToken = (MyCancelObject)state; 

    if (!sourceToken.CancelToken.IsCancellationRequested) 
    { 
    //Check database to see if cancelled -- if so, set to cancelled 
    sourceToken.CancelToken.Cancel(); 
    } 
} 

private void SomeFunc() 
{ 
    Task.StartNew(() => 
    { 
    MyCancelObject myCancelObject = new MyCancelObject(
     databaseId, 
     new CancellationTokenSource()); 
    System.Threading.Timer cancelTimer = new Timer(
     new TimerCallback(CheckIfTaskCancelled), 
     myCancelObject, 
     10000, 
     10000);   
    Task[] someTasks = new Task[someNumberOfTasks]; 

    for (int i = 0; i < someNumberOfTasks; i++) 
     someTasks[i] = Task.Factory.StartNew(
     () => 
     { 
      DoSomeWork(someObject, myCancelObject.CancelToken.Token); 
     }, 
     TaskCreationOptions.AttachedToParent | TaskCreationOptions.LongRunning, 
     myCancelObject.CancelToken.Token); 

    try 
    { 
     Task.WaitAll(someTasks, cts); 
    } 
    catch (AggregateException) 
    { 
     //Do stuff to handle 
    } 
    catch (OperationCanceledException) 
    { 
     //Should I call Task.WaitAll(someTasks) again?? 
     //I want to be able to dispose. 
    } 
    } 
} 
+0

मैं कुछ कोड का परीक्षण किया और पाया कि 'Task.WaitAll' सुरक्षित रूप से कार्य अभी भी चल रहा जा सकता है कि के लिए इंतजार करना फिर से कहा जा सकता है। उसके बाद, उनका निपटारा किया जा सकता है। मैं अभी भी जानना चाहूंगा कि हालांकि इसे संभालने के अन्य तरीके हैं या नहीं। –

+2

यह केवल आपके अपने प्रश्न के लिए स्वीकार्य नहीं है, लेकिन इसे प्रोत्साहित किया जाता है। एक उत्तर पोस्ट करने के लिए स्वतंत्र महसूस करें और इसे स्वीकार करें यदि आपको लगता है कि आपने इसे समझ लिया है। –

उत्तर

2

मुझे लगता है कि मैंने इसे समझ लिया है, लेकिन कोई भी जो कुछ और उपयोगी जोड़ना चाहता है, स्वागत से अधिक है।

मैं बस फिर Task.WaitAll() बुलाया कैच ब्लॉक से अन्य कार्यों के समाप्त होने की प्रतीक्षा करने के लिए। आखिरकार पूरा होने के बाद, मैंने आखिरकार सरणी में सभी कार्यों को साफ करने के लिए ब्लॉक किया है।

try 
{ 
Task.WaitAll(someTaskArray, cancelToken) 
} 
catch (OperationCanceledException) 
{ 
Task.WaitAll(someTaskArray); 
} 
finally 
{ 
for (int i = 0; i < someTaskArray.Length; i++) 
someTaskArray[i].Dispose(); 
} 
+0

खान से भी बदतर है कि लगता है, आदेश मैं करना पड़ा इंतजार करना में: कोशिश {Tasks.WaitAll (कार्य); } पकड़ (OperationCanceledException) { कोशिश {Tasks.WaitAll (कार्य); } पकड़ (AggregateException) {Tasks.WaitAll (कार्य); } } फिर निपटाने ... सुनिश्चित नहीं हैं कि क्यों, लेकिन यह काम करने के लिए लगता है। – Tom

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