-1

首先,我创建了这个类:

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;
        BackgroundWorker mainBackGroundWorker;
        BackgroundWorker secondryBackGroundWorker;
        WebcrawlerConfiguration webcrawlerCFG;
        List<WebCrawler> webcrawlers;
        int maxlevels;
        public event EventHandler<BackgroundWebCrawlingProgressEventHandler> ProgressEvent;
        // mainBack to make doWork event 
        // function that called start that get list<string> websitestocrawl anbd get int number how many threads to work at once ! in Form1 to make start to be public
        // to make progress event to the main background ! mainBack first time to make it to work without progress maybe !
        // to make getList function to get all lists from the webcrawlers instances !
        // in the mainBack to check and create instances for secondryBackground each time.
        // to the seocndry to make DoWork as it is now !
        // in the secondry to call the webcrawler from the class WebCrawler .
        // since WebCrawler is a class in the main background DoWork event before calling for a new thread for the secondry to make a new instance to the webCrawler class !!!
        // to call to the FUNCTION webCrawler to use the e.Argument to get create instance of the webCrawler function.
        // to make the progress event in the end to report for labels and richtextboxes in Form1. maybe in Form1 to use invokes for this event.
        // the function start will get parameters she need and that webcrawer need from webcrawler cfg class. this list to send to each webcrawler instance.

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

        private void mainBackGroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i < WebSitesToCrawl.Count; i++)
            {

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

        private void secondryBackGroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {



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

        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)
        {
            // ok .. so now you get the data here in e
            // and here you should call the event to form1 
            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); /// send the data + additional data from this class to Form1..
                                       /// 
            /*
             * temp_arr[0] = csFiles;
                temp_arr[1] = mainUrl;
                temp_arr[2] = levels;
                temp_arr[3] = currentCrawlingSite;
                temp_arr[4] = sitesToCrawl;*/
        }

        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) // probably you need to some vars here to...
        {

            // some_params to put in evenetArgs..
            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]
                    });
        }

    }
}

在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";
            }
            else
            {
                label6.Text = "Process Completed";
            }
            button6.Enabled = true;
            button4.Enabled = false;
            button5.Enabled = false;
            listBox1.Enabled = true;

        }

但是我在 Form1 中没有任何 backgroundworker1 并且这个完成的事件没有以任何方式连接到上面其他类中的任何 backgroundworkers。

当后台工作人员完成时,我如何使用/制作完成的事件将起作用?

这是 Form1 中启动后台工作程序的按钮单击事件:

private void button1_Click(object sender, EventArgs e)
        {
            WebcrawlerConfiguration wcfg = new WebcrawlerConfiguration();
            BackgroundWebCrawling bgwc = new BackgroundWebCrawling();

            wcfg.downloadcontent = downLoadImages;
            wcfg.failedUrls = failedUrls;
            wcfg.localy = LocalyKeyWords;
            wcfg.removeext = removeExt;
            wcfg.toCancel = cancel;
            bgwc.Start(sites, 3, (int)numericUpDown1.Value, wcfg);

            offlineOnline = false;
            init();
            bgwc.ProgressEvent += new EventHandler<BackgroundWebCrawling.BackgroundWebCrawlingProgressEventHandler>(bgwc_ProgressEvent);
        }
4

1 回答 1

1

目前尚不清楚您希望将哪个后台工作人员连接到事件,但您所要做的就是:

worker.RunWorkerCompleted+= 
        new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);

编辑:
因此,如果您希望在mainBackGroundWorker完成后触发此功能,它应该是:

mainBackGroundWorker.RunWorkerCompleted+= 
    new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);

如果你希望它在secondryBackGroundWorker完成后被触发,它应该是:

secondryBackGroundWorker.RunWorkerCompleted+= 
    new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);

边注

在使用 backgroundWorker 时,我总是方便地使用 @Keith模板

BackgroundWorker bw = new BackgroundWorker { WorkerReportsProgress = true };

bw.DoWork += (sender, e) => 
   {
       //what happens here must not touch the form
       //as it's in a different thread
   };

bw.ProgressChanged += ( sender, e ) =>
   {
       //update progress bars here
   };

bw.RunWorkerCompleted += (sender, e) => 
   {
       //now you're back in the UI thread you can update the form
       //remember to dispose of bw now
   };

worker.RunWorkerAsync();
于 2013-09-10T03:01:32.737 回答