-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";
            }

问题是为什么当我单击按钮并等待首先完成该过程时它没有中止操作?也许我也需要以某种方式停止/中止第二个背景?

4

1 回答 1

0

首先,这似乎是矫枉过正的代码,但也许有必要......

其次,你的取消实际上并没有取消任何东西,它只是设置了一个你必须采取行动的标志,当你响应那个标志时,你只是在breaking,然后你等待计数回到 0。如果你想要立即停止,然后不要breakreturn

休息后,您仍在工作人员中执行以下操作。您也可以counter在取消时将其设置为 0。但是,回报更能证明未来。

while (counter > 0)
{
    Thread.Sleep(10);
}
于 2013-10-15T17:20:00.563 回答