0

WebからダウンロードするURL(約800)がたくさんあります。私はクラスを持っています:HttpWebRequestクラスで使用してhtmlページをダウンロードして取得するHttpDownloader.cs。その後、正規表現のページにアクセスします。

BackgroundWorkerコンポーネントを使用したいのですが、すべてのページで使用する方法がわかりません。ループ、またはそのようなものによって。

私のコード:

ThreadPoolを使ってみましたが、実際に問題が発生しました。4つのURLで試しましたが、機能しませんでした。

      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でdataBaseと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 に答える