2013-10-15 38 views
-2

這是我有兩個背景工作者的背景工作者。爲什麼當我點擊取消操作時,它並沒有立即停止背景工作?

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using HtmlAgilityPack; 
using System.Net; 
using System.Windows.Forms; 
using System.ComponentModel; 
using System.Threading; 

namespace GatherLinks 
{ 
    class BackgroundWebCrawling 
    { 
     public string f; 
     int counter = 0; 
     List<string> WebSitesToCrawl; 
     int MaxSimultaneousThreads; 
     public BackgroundWorker mainBackGroundWorker; 
     BackgroundWorker secondryBackGroundWorker; 
     WebcrawlerConfiguration webcrawlerCFG; 
     List<WebCrawler> webcrawlers; 
     int maxlevels; 
     public event EventHandler<BackgroundWebCrawlingProgressEventHandler> ProgressEvent; 
     ManualResetEvent _busy = new ManualResetEvent(true); 


     public BackgroundWebCrawling() 
     { 
      webcrawlers = new List<WebCrawler>(); 
      mainBackGroundWorker = new BackgroundWorker(); 
      mainBackGroundWorker.WorkerSupportsCancellation = true; 
      mainBackGroundWorker.DoWork += mainBackGroundWorker_DoWork; 
     } 

     private void mainBackGroundWorker_DoWork(object sender, DoWorkEventArgs e) 
     { 
      try 
      { 
       BackgroundWorker worker = sender as BackgroundWorker; 
       for (int i = 0; i < WebSitesToCrawl.Count; i++) 
       { 
        _busy.WaitOne(); 
        if ((worker.CancellationPending == true)) 
        { 
         e.Cancel = true; 
         break; 
        } 
        while (counter >= MaxSimultaneousThreads) 
        { 
         Thread.Sleep(10); 
        } 


        WebCrawler wc = new WebCrawler(webcrawlerCFG); 
        webcrawlers.Add(wc); 
        counter++; 
        secondryBackGroundWorker = new BackgroundWorker(); 
        secondryBackGroundWorker.DoWork += secondryBackGroundWorker_DoWork; 
        object[] args = new object[] { wc, WebSitesToCrawl[i] }; 
        secondryBackGroundWorker.RunWorkerAsync(args); 



       } 
       while (counter > 0) 
       { 
        Thread.Sleep(10); 
       } 
      } 
      catch 
      { 
       MessageBox.Show("err"); 
      } 
     } 

     private void secondryBackGroundWorker_DoWork(object sender, DoWorkEventArgs e) 
     { 


      try 
      { 
       object[] args = (object[])e.Argument; 
       WebCrawler wc = (WebCrawler)args[0]; 
       string mainUrl = (string)args[1]; 
       wc.ProgressEvent += new EventHandler<WebCrawler.WebCrawlerProgressEventHandler>(x_ProgressEvent); 
       wc.webCrawler(mainUrl, maxlevels); 


       counter--; 
      } 
      catch 
      { 
       MessageBox.Show("err"); 
      } 
     } 

     public void Start(List<string> sitestocrawl, int threadsNumber, int maxlevels, WebcrawlerConfiguration wccfg) 
     { 
      this.maxlevels = maxlevels; 
      webcrawlerCFG = wccfg; 
      WebSitesToCrawl = sitestocrawl; 
      MaxSimultaneousThreads = threadsNumber; 
      mainBackGroundWorker.RunWorkerAsync(); 
     } 

     private void x_ProgressEvent(object sender, WebCrawler.WebCrawlerProgressEventHandler e) 
     { 

      Object[] temp_arr = new Object[8]; 
      temp_arr[0] = e.csFiles; 
      temp_arr[1] = e.mainUrl; 
      temp_arr[2] = e.levels; 
      temp_arr[3] = e.currentCrawlingSite; 
      temp_arr[4] = e.sitesToCrawl; 
      temp_arr[5] = e.done; 
      temp_arr[6] = e.failedUrls; 
      temp_arr[7] = e.failed; 
      OnProgressEvent(temp_arr); 
     } 

     private void GetLists(List<string> allWebSites) 
     { 

     } 

     public class BackgroundWebCrawlingProgressEventHandler : EventArgs 
     { 
      public List<string> csFiles { get; set; } 
      public string mainUrl { get; set; } 
      public int levels { get; set; } 
      public List<string> currentCrawlingSite { get; set; } 
      public List<string> sitesToCrawl { get; set; } 
      public bool done { get; set; } 
      public int failedUrls { get; set; } 
      public bool failed { get; set; } 
     } 

     protected void OnProgressEvent(Object[] some_params) 
     { 


      if (ProgressEvent != null) 
       ProgressEvent(this, 
        new BackgroundWebCrawlingProgressEventHandler() 
        { 
         csFiles = (List<string>)some_params[0], 
         mainUrl = (string)some_params[1], 
         levels = (int)some_params[2], 
         currentCrawlingSite = (List<string>)some_params[3], 
         sitesToCrawl = (List<string>)some_params[4], 
         done = (bool)some_params[5], 
         failedUrls = (int)some_params[6], 
         failed = (bool)some_params[7] 
        }); 
     } 

     private void PauseWorker() 
     { 
      if (mainBackGroundWorker.IsBusy) 
      { 
       _busy.Reset(); 
      } 
     } 

     private void ContinueWorker() 
     { 
      _busy.Set(); 
     } 

     public void CancelWorker() 
     { 
      ContinueWorker(); 
      mainBackGroundWorker.CancelAsync(); 
     } 

    } 
} 

這是按鈕單擊事件我點擊中止操作:

private void button3_Click(object sender, EventArgs e) 
     { 
      bgwc.CancelWorker(); 
      cancel = true; 
      wcfg.toCancel = cancel; 
     } 

當我點擊按鈕,它要去BackgroundWebCrawling類和做:

public void CancelWorker() 
     { 
      ContinueWorker(); 
      mainBackGroundWorker.CancelAsync(); 
     } 

但對於有些原因,而是立即停止背景工作者等待/掛起,直到它將完成當前過程約2-3-5秒,然後停止。 而是立即停止其去到Form1,做這部分:

private void bgwc_ProgressEvent(object sender, BackgroundWebCrawling.BackgroundWebCrawlingProgressEventHandler e) 
     { 
      this.Invoke(new MethodInvoker(delegate { label7.Text = e.sitesToCrawl.Count.ToString(); })); 
      this.Invoke(new MethodInvoker(delegate { ColorText.Texts(richTextBox1, "Level: " + e.levels.ToString(), Color.Green); })); 
      this.Invoke(new MethodInvoker(delegate { ColorText.Texts(richTextBox1, " Loading The Url: ", Color.Red); })); 
      this.Invoke(new MethodInvoker(delegate { ColorText.Texts(richTextBox1, e.mainUrl + "...", Color.Blue); })); 
      if (e.done == true) 
      { 


        this.Invoke(new MethodInvoker(delegate { ColorText.Texts(richTextBox1, " Done " + Environment.NewLine, Color.Red); })); 
        doneWebPages++; 
        this.Invoke(new MethodInvoker(delegate { label12.Text = doneWebPages.ToString(); })); 

      } 
      if (e.failed == true) 
      { 
       this.Invoke(new MethodInvoker(delegate { label10.Text = e.failedUrls.ToString(); })); 
       this.Invoke(new MethodInvoker(delegate { ColorText.Texts(richTextBox1, " Failed " + Environment.NewLine, Color.Green); })); 
      } 
      if (e.failedUrls > 0) 
      { 
       this.Invoke(new MethodInvoker(delegate { label10.Text = e.failedUrls.ToString(); })); 
       e.failed = true; 
       if (e.failed == true) 
       { 
        this.Invoke(new MethodInvoker(delegate { ColorText.Texts(richTextBox1, " Failed " + Environment.NewLine, Color.Green); })); 
        e.failed = false; 
       } 
      } 
      this.Invoke(new MethodInvoker(delegate { label13.Text = (e.failedUrls + doneWebPages).ToString(); })); 
     } 

後,其要回BackgroundWebCrawling類和這樣做:

if (ProgressEvent != null) 
       ProgressEvent(this, 
        new BackgroundWebCrawlingProgressEventHandler() 
        { 
         csFiles = (List<string>)some_params[0], 
         mainUrl = (string)some_params[1], 
         levels = (int)some_params[2], 
         currentCrawlingSite = (List<string>)some_params[3], 
         sitesToCrawl = (List<string>)some_params[4], 
         done = (bool)some_params[5], 
         failedUrls = (int)some_params[6], 
         failed = (bool)some_params[7] 
        }); 

然後做同一類這一行:

OnProgressEvent(temp_arr); ///從這個類到Form1發送數據+附加數據..

而這一切之後Š獲得在Form1上完成的事件:

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
     { 
      button3.Enabled = false; 
      checkBox1.Enabled = true; 
      checkBox2.Enabled = true; 
      numericUpDown1.Enabled = true; 
      button1.Enabled = true; 
      button2.Enabled = true; 
      this.Text = "Web Crawling"; 
      if (cancel == true) 
      { 
       label6.Text = "Process Cancelled"; 
      } 

的問題是,爲什麼它不放棄經營權當我點擊按鈕和等待第一個完成該過程? 也許我需要停止/中止第二個背景嗎?

+0

不,看來第二個(secondryBackGroundWorker)不會影響當我取消操作。當我取消時,至少它不會去secondryBackGroundWorker_DoWork事件。 –

+0

您是否將'WorkerSupportsCancellation'設置爲'true'? –

+1

當然,這將需要一段時間。 BGW正在執行一個調用Sleep()並且不關注CancellationPending的循環。它可能永遠不會停止,在兩個線程中更改* count *基本上不是線程安全的。 –

回答

0

首先,這似乎有點小題大做代碼,但也許有必要...

其次,你的取消是不實際取消任何東西,它只是設置,你必須採取行動的一個標誌,當您迴應如果你想立即停止,那麼不要breakreturn

你休息後,你仍然在做以下事情在你的工人。也可以在取消時將counter設置爲0。但是,回報是更有前途的證據。

while (counter > 0) 
{ 
    Thread.Sleep(10); 
} 
相關問題