2012-05-07 16 views
5

पर काम नहीं कर रहा है मेरे पास एक पृष्ठभूमि कार्यकर्ता है जो एक ही प्रक्रिया चलाता है। मैं प्रसंस्करण को रद्द करने में सक्षम होना चाहता हूं, लेकिन जब मैं CancelAsync() विधि को कॉल करता हूं, तो यह वास्तव में कभी भी रद्द नहीं होता है। मैं कहाँ गलत हूँ?Backgroundworker.CancelAsync()

 private void bgw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     BackgroundWorker b = sender as BackgroundWorker; 

     if (b != null) 
     { 
      if (!b.CancellationPending) 
      { 
       try 
       { 
        // Let's run the process as a backgroundworker so we have the ability to cancel the search, and/or be able to view results while it's still searching 
        ProcessParameters pp = e.Argument as ProcessParameters; 

        if (pp.DoReplace) 
         results = FindReplace.FindReplace.FindAndReplace(pp.PathToSearch, pp.FindText, pp.ReplaceText, pp.UseRegularExpressions, pp.IncludeList, pp.ExcludeList, pp.RecurseSubdirectories, pp.IgnoreCase); 
        else 
         results = FindReplace.FindReplace.Find(pp.PathToSearch, pp.FindText, pp.UseRegularExpressions, pp.IncludeList, pp.ExcludeList, pp.RecurseSubdirectories, pp.IgnoreCase); 
       } 
       catch (Exception ex) 
       { 
        MessageBox.Show(ex.ToString()); 
       } 
      } 
      else 
      { 
       // Cancel was clicked 
       e.Cancel = true; 
      } 
     } 
    } 

यहाँ विधि है कि प्रसंस्करण शुरू होता है::

यहाँ DoWork() विधि है

 private void btnGo_Click(object sender, EventArgs e) 
    { 
     if (btnGo.Text == "Cancel") 
     { 
      if (DialogResult.Yes == MessageBox.Show("Are you sure you wish to cancel?", "Cancel Requested", MessageBoxButtons.YesNo, MessageBoxIcon.Question)) 
       bgw.CancelAsync(); 

      return; 
     } 

     if (tbFind.Text.Length == 0) 
     { 
      MessageBox.Show("Find text is not valid."); 
      return; 
     } 

     tbFound.Text = String.Empty; 
     tbFoundInThisFile.Text = String.Empty; 
     lvResults.Items.Clear(); 
     includeList = null; 
     excludeList = null; 
     results = null; 

     if (radDirectory.Checked && !radFile.Checked) 
     { 
      includeList = BuildIncludeExcludeList(tbIncludeFiles.Text); 
      excludeList = BuildIncludeExcludeList(tbExcludeFiles.Text); 
     } 

     ProcessParameters pp = null; 

     if (chkReplace.Checked) 
      pp = new ProcessParameters(tbPath.Text, tbFind.Text, tbReplace.Text, chkUseRegEx.Checked, includeList, excludeList, chkRecursion.Checked, chkIgnoreCase.Checked, true); 
     else 
      pp = new ProcessParameters(tbPath.Text, tbFind.Text, chkUseRegEx.Checked, includeList, excludeList, chkRecursion.Checked, chkIgnoreCase.Checked, false); 

     bgw.RunWorkerAsync(pp); 

     // Toggle fields to locked while it's running 
     btnGo.Text = "Cancel"; 
    } 

और यहाँ WorkerCompleted() घटना है:

 private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     btnGo.Text = "Go"; 

     string message = String.Empty; 
     const string caption = "FindAndReplace is Complete"; 

     if (!e.Cancelled) 
     { 
      if (results != null) 
      { 
       tbFound.Text = results.Found.ToString(); 
       tbSearched.Text = results.FilesSearched.ToString(); 
       tbSkipped.Text = results.FilesSkipped.ToString(); 

       message = String.Format("Search finished resulting in {0} match(es).", results.Found); 
      } 
      else 
       message = "The FindAndReplace results were empty. The process was cancelled or there was an error during operation."; 
     } 
     else 
      message = "The FindAndReplace process was cancelled."; 

     if (e.Error != null) 
      message += String.Format("{0}{0}There was an error during processing: {1}", Environment.NewLine, e.Error); 

     MessageBox.Show(message, caption); 
    } 
+1

आपके पास केवल एक बहुत छोटी विंडो है जो रद्द करने के लिए जांचती है। आप इसे गर्म नहीं करेंगे। –

+1

ओटी लेकिन आपके पूर्ण हैंडलर में ई.इरर की जांच पहले जाना चाहिए। –

उत्तर

5

आप वास्तव में कार्रवाई को रद्द करने का कोई तरीका नहीं है। समस्या यह है कि यह कोड

   if (pp.DoReplace) 
        results = FindReplace.FindReplace.FindAndReplace(pp.PathToSearch, pp.FindText, pp.ReplaceText, pp.UseRegularExpressions, pp.IncludeList, pp.ExcludeList, pp.RecurseSubdirectories, pp.IgnoreCase); 
       else 
        results = FindReplace.FindReplace.Find(pp.PathToSearch, pp.FindText, pp.UseRegularExpressions, pp.IncludeList, pp.ExcludeList, pp.RecurseSubdirectories, pp.IgnoreCase); 

एक बार यह शुरू होने के बाद तोड़ने का कोई तरीका नहीं है। तो, क्या हवाएं हो रही हैं कि आप रद्द कर देते हैं, लेकिन रद्द होने से पहले रद्द नहीं किया जाता है जब तक आप कार्रवाई शुरू होने से पहले रद्द कर देते हैं। एक बार जब यह कार्य पूरा हो जाए, तो DoWork विधि सफलतापूर्वक लौट आती है और पृष्ठभूमि कार्यकर्ता रद्दीकरण को कभी भी ट्रिगर नहीं करता है।

संपादित करें: आप एक तरह से छोटे मात्रा है कि तब हो सकता है में पाठ को तोड़ने के लिए है, तो "खोज की है और प्रतिस्थापित", आप उन क्षेत्रों के माध्यम से लूप सकता है और प्रत्येक पाश में निरस्तीकरण की जांच करते हैं। आपको यह सुनिश्चित करना होगा कि आप उन ब्रेक सीमाओं में खोज स्ट्रिंग के लिए खाते हैं, हालांकि, यह वास्तव में रद्दीकरण की अनुमति देने के लिए लंबे समय तक ले सकता है।

+0

यही वह है जिसे मैं डरता था। मेरी "पृष्ठभूमि" प्रक्रिया एक लंबी प्रक्रिया है, इसलिए मुझे यकीन नहीं था कि उस प्रक्रिया को कैसे मारना है। क्या ऐसा करने में सक्षम होने का कोई तरीका है? – ganders

+3

चूंकि आपकी DoWork विधि मूल रूप से केवल एक ही कमांड चलाती है, तो नहीं, वास्तव में एक आदेश को रद्द करने का कोई तरीका नहीं है। आप केवल आदेशों के बीच रद्दीकरण की जांच कर सकते हैं (विशेष रूप से यदि आप लूपिंग कर रहे हैं)। आप शायद छोटे सेगमेंट में पाठ को तोड़ सकते हैं, फिर 'लूपरस्थल' के माध्यम से लूप, प्रत्येक लूप पर रद्दीकरण की जांच कर सकते हैं। – saluce

+0

तो, ऐसा लगता है कि मुझे बैकग्राउंडवर्कर का उपयोग नहीं करना चाहिए, लेकिन केवल एक अलग थ्रेड का उपयोग करें (शायद पृष्ठभूमि कार्यकर्ता से कहा जाता है, इसलिए मैं अभी भी प्रगति की रिपोर्ट कर सकता हूं?) फिर जब मेरा रद्द क्लिक किया जाता है, तो मैं थ्रेड कॉल कर सकता हूं। ऑबॉर्ट (), या कुछ इस तरह का? क्या वह "स्मार्ट" करना है? – ganders

7

CancelAsync वास्तव में आपके धागे या किसी को रोक नहीं है जैसी चीज। यह कार्यकर्ता धागे को एक संदेश भेजता है कि काम होना चाहिए BackgroundWorker.CancellationPending के माध्यम से रद्द किया गया। आपके DoWork पृष्ठभूमि में भाग लेने वाले प्रतिनिधि को समय-समय पर इस संपत्ति की जांच करनी चाहिए और रद्दीकरण को स्वयं ही संभालना चाहिए।

और पढ़ें here

3

आपका कोड सही है, लेकिन यदि आप इसे फिर से ध्यान से पढ़ते हैं, तो आप देखेंगे कि पृष्ठभूमि कार्यकर्ता शुरू होने के बाद, जल्द ही यह रद्द करने की जांच से बाहर हो जाता है। उसके बाद भी अगर आप रद्द करने का प्रयास करते हैं, तो यह अब और काम नहीं करेगा।

आपको अपनी खोज को फिर से डिजाइन करना होगा और रद्द करने की जांच को शामिल करने के लिए एल्गोरिदम को प्रतिस्थापित करना होगा, ताकि आपकी इच्छानुसार रद्दीकरण का समर्थन किया जा सके।