2012-01-31 11 views
7

मुझे सी # में इस कार्य को रद्द करने का तरीका पता चल रहा है। मुझे धागे को संभालने की पूरी समझ नहीं है और मैंने कुछ सरल कोड उदाहरणों के लिए गूगलिंग की कोशिश की है ताकि मुझे मदद मिल सके लेकिन मुझे वास्तव में कोई जगह नहीं मिली है। यहाँ कोड का टुकड़ा मैं पर काम कर रहा हूँ है:एक कार्य को रद्द करना जो यूआरएल को अतुल्यकालिक रूप से पुनर्प्राप्त करता है

var tasks = urls.Select(url => Task.Factory.StartNew(
state => 
{ 
    using (var client = new WebClient()) 
    { 

     lock (this) 
     { 

     // code to download stuff from URL 

     } 

    } 
}, url)).ToArray(); 

    try 
    { 
     Task.WaitAll(tasks); 
    } 
    catch (Exception e) 
    { 
     textBox2.AppendText("Error: " + e.ToString()); 
    } 

कहाँ "यूआरएल" URL की एक सरणी है। क्या इसे बनाने का कोई आसान तरीका है, जब मैं अपने प्रोग्राम में एक बटन क्लिक करता हूं, तो यूआरएल डाउनलोड करना पूरी तरह से बंद हो जाता है? साथ ही, चिपकाया गया कोड स्निपेट एक ऐसे फ़ंक्शन में है जो BackgroundWorker1 कॉल करता है, जो मुझे लगता है कि चीजों को थोड़ा और जटिल बना सकता है। (कारण है कि मैं एक BackgroundWorker है तो यूआई बंद नहीं करता है, जबकि यह यूआरएल को डाउनलोड कर रहा है।)

हैं कि किसी भी तरह से एक सा भ्रामक है, यहाँ मैं क्या साथ प्राप्त करने के लिए कोशिश कर रहा था की एक रूपरेखा है मेरी कोड:

  • मेरे पास URL की एक सरणी है, मैं यूआई को लॉक किए बिना प्रत्येक यूआरएल को असीमित रूप से डाउनलोड करना चाहता हूं।
  • मैं अधिमानतः उपयोगकर्ता को बटन को क्लिक करके यूआरएल डाउनलोड करने से रोकने के लिए पसंद करता हूं, थ्रेड को काफी रद्द कर देता हूं।
  • जब उपयोगकर्ता दोबारा बटन क्लिक करता है, तो प्रोग्राम उस सरणी से फिर से यूआरएल डाउनलोड करता है।

अग्रिम धन्यवाद।

+0

कृपया अपने प्रश्न शीर्षक में टैग शामिल न करें; यह सिर्फ उन लोगों के लिए अधिक काम करता है जो SO पर स्थिरता की परवाह करते हैं। –

उत्तर

1

यह नहीं पता कि यह करने का सही तरीका है या नहीं, लेकिन मैं निम्नलिखित कोड का उपयोग करके कार्यों को रद्द करने में सक्षम हूं। मैंने ListBox और ProgressBar के साथ एक फॉर्म बनाया है, इसलिए मैं BackgroundWorker की ProgressChanged ईवेंट को बढ़ा रहा हूं और प्रबंधित कर रहा हूं। उम्मीद है कि यह आपको किसी भी तरह से मदद करता है।

void bw_DoWork(object sender, DoWorkEventArgs e) 
{ 
    CancellationTokenSource _tokenSource = new CancellationTokenSource(); 
    CancellationToken _token = _tokenSource.Token; 

    var urls = e.Argument as IEnumerable<string>; 

    _token = new CancellationToken(); 

    if (urls == null) return; 

    var i = 0; 
    var a = 100/urls.Count(); 

    var sb = new StringBuilder(); 
    var t = urls.Select(url => Task.Factory.StartNew(
        (u) =>{ 
         using (var wc = new WebClient()) 
         { 
          lock (this){ 
           var s = wc.DownloadString(u.ToString()); 
           sb.AppendFormat("{1}:{0}\r\n", "", u); 
          } 
         } 

        if (Worker.CancellationPending){ 
         //MAGIC HAPPENS HERE, IF BackgroundWorker IS REQUESTED 
         //TO CANCEL, WE CANCEL CancellationTokenSource 
         _tokenSource.Cancel(); 
        } 

        //IF CANCELATION REQUESTED VIA CancellationTokenSource 
        //THROW EXCEPTION WHICH WILL ADD TO AggreegateException 
        _token.ThrowIfCancellationRequested(); 

        //YOU CAN IGNORE FOLLOWING 2 LINES 
        i += a; 
        Worker.ReportProgress(i, u); 
    }, url, _token)).ToArray(); 

    try 
    { 
     Task.WaitAll(t); 
    } 
    catch (AggregateException age) 
    { 
     if (age.InnerException is OperationCanceledException) 
      sb.Append("Task canceled"); 
    } 
    catch (Exception ex) 
    { 
     sb.Append(ex.Message); 
    } 

    e.Result = sb; 
} 
+0

वाह, वह कोड उदाहरण बहुत उपयोगी था, मुझे लगता है कि कोड का अपना टुकड़ा काम करता है, और धागा सफलतापूर्वक रद्द कर दिया गया था। मैं अभी तक बहुत उत्साहित नहीं होना चाहता हूं, हालांकि कुछ हमेशा आ सकता है। :) – Chrispy

1

वेब क्लाइंट के साथ, आप एसिंक्रोनस ऑपरेशन को रद्द करने के लिए CancelAsync विधि का उपयोग कर सकते हैं।

Factory.StartNew के माध्यम से शुरू किए जा रहे कार्यों को रद्द करने के लिए, आपको CancellationTokenSource का उपयोग करना चाहिए। आपको कार्यों में CancellationTokenSource.Token पास करने की आवश्यकता है (और आप पूछ सकते हैं कि टोकन पहले से ही token.IsCancellationRequested का उपयोग कर रद्द कर दिया गया है), और रद्द करने के रूप में टोकन सेट करने के लिए आप CancellationTokenSource.Cancel() पर कॉल करेंगे।

+0

चीयर्स, मैं फैक्टरी के संबंध में इसे याद रखना सुनिश्चित करूंगा। स्टार्टन्यू – Chrispy

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