首先我创建了这个课程:
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,并且这个完成的事件没有以任何方式连接到上面其他类的任何后台工作者。
当backgroundworker完成后,如何使用/ make,完成的事件将起作用?
这是Form1中启动backgroundworker的按钮单击事件:
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);
}
答案 0 :(得分:1)
目前尚不清楚您希望将哪个后台工作人员连接到该事件,但您需要做的就是:
worker.RunWorkerCompleted+=
new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
修改强>
因此,如果您希望在mainBackGroundWorker
完成后触发此功能,则应该是:
mainBackGroundWorker.RunWorkerCompleted+=
new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
如果您希望在secondryBackGroundWorker
完成后触发它,则应该是:
secondryBackGroundWorker.RunWorkerCompleted+=
new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
使用backgroundWorker时,我总是方便地使用@Keith template
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();