0

我有很多网址(大约 800 个)要从网上下载。我有一个类:HttpDownloader.cs,它与 HttpWebRequest 类一起使用来下载和获取 html 页面。之后,我通过正则表达式对页面进行解析。

我想使用 BackgroundWorker 组件,但我不知道如何为所有页面执行它。通过一个循环,或类似的东西。

我的代码:

我尝试与 ThreadPool 一起使用,它确实有问题。我尝试了 4 个网址,但没有成功。

      foreach (string link in MyListOfUrls)
      {
 ThreadPool.QueueUserWorkItem((o) => {

           HttpDownloader httpDownload = new HttpDownloader(link);
           string htmlDoc = httpDownload.GetPage();//get the html of the page 
           HtmlDocument doc=doc.LoadHtml(htmlDoc);//load html string to doc for pharsing
           DoPharsing();//my func for pharsing
           Save();//save into dataBase
  });
      }

因为我在 func 中使用与数据库和 DataTable 的连接,所以在使用 ThreadPool 时出现异常:

“函数评估已禁用,因为之前的函数评估超时。您必须继续执行才能重新启用函数评估。”

所以,我无法从 DataTable 中获取数据。也许我需要全部下载,然后进行解析并保存?

如何通过 BackgroundWorker 组件将其更改为异步?

ps 不要建议我使用 Async Tpc,因为我没有设法下载它。

谢谢

4

2 回答 2

1

这取决于您要拆分的内容、整个循环,或者只是循环的下载部分。显然,如果您希望整个循环在后台运行,那么最简单的方法就是使用 ThreadPool。

请注意,您可能必须更改解析和保存函数,以便将 HTML 文档传递给每个函数。

ThreadPool.QueueUserWorkItem((o) => {
  foreach (string link in MyListOfUrls)
  {
    HttpDownloader httpDownload = new HttpDownloader(link);
    string htmlDoc = httpDownload.GetPage();//get the html of the page
    HtmlDocument doc=doc.LoadHtml(htmlDoc);//load html string to doc for pharsing
    var result = DoPharsing(doc);//my func for pharsing
    Save(result);//save into dataBase
 } 
});

或者

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (o, e) => { 
  foreach (string link in MyListOfUrls)
  {
    HttpDownloader httpDownload = new HttpDownloader(link);
    string htmlDoc = httpDownload.GetPage();//get the html of the page
    HtmlDocument doc=doc.LoadHtml(htmlDoc);//load html string to doc for pharsing
    var result = DoPharsing(doc);//my func for pharsing
    Save(result);//save into dataBase
 } 
};
worker.RunWorkerCompleted += (o, e) => {
   // Job completed
}
worker.RunWorkerAsync();

要同时下载多个链接,只需切换您创建线程的位置。:

foreach (string link in MyListOfUrls)
{
  ThreadPool.QueueUserWorkItem((o) => {
    HttpDownloader httpDownload = new HttpDownloader(link);
    string htmlDoc = httpDownload.GetPage();//get the html of the page
    HtmlDocument doc=doc.LoadHtml(htmlDoc);//load html string to doc for pharsing
    var result = DoPharsing(doc);//my func for pharsing
    Save(result);//save into dataBase
  });
 } 

(我认为这里的线程池比创建数百个后台工作者更好)。

于 2012-05-01T08:58:03.967 回答
0

我最终找到了答案
这是我的代码:

static BackgroundWorker[] d=new BackgroundWorker[MyListOfUrls.Length];
  string html=new string[MyListOfUrls.Length]

  static void Main(string[] args)
  {
    for (int i = 0; i < MyListOfUrls.Length; i++)
    {
         d[i]=new BackgroundWorker{WorkerReportsProgress=true};
         d[i].DoWork += new DoWorkEventHandler(worker2_DoWork);
         d[i].ProgressChanged += new ProgressChangedEventHandler(Program_ProgressChanged);
         d[i].RunWorkerAsync(i);
         d[i].RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunWorkerCompleted);
         Thread.Sleep(1000);
    }
  }  

  static void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
  {
      Console.WriteLine("End");
  }

  static void Program_ProgressChanged(object sender, ProgressChangedEventArgs e)
  {
      Console.WriteLine(e.ProgressPercentage.ToString());
  }

  static void worker2_DoWork(object sender, DoWorkEventArgs e)
  {
      var worker = (BackgroundWorker)sender;
      worker.ReportProgress((int)e.Argument);

      HttpDownloader httpDownload = new HttpDownloader(link);
      html[(int)e.Argument] = httpDownload.GetPage();

      Thread.Sleep(500);
  }

如果有人知道如何做得更好,我会很高兴。塔克斯,查尼

于 2012-05-01T17:01:10.337 回答