2

これまで、Web サイトをクロールするシングル スレッド アプリを使用していました。
高速化したいので、マルチスレッドアプリにリビルドしてみました。これが
私がすることです: WebBrowser オブジェクトを保持するクロール クラスがあります。これは私がスレッドを開始する方法です:

 Crawler c1 = new Crawler();  
 Thread t1 = new Thread(new ThreadStart(c1.Crawl));  
 t1.SetApartmentState(ApartmentState.STA);
 t1.start()

スレッドは次の関数に到達します。

 LogIn(bool isInit)  
 {  
   browser = new WebBrowser();
   NavigateAndWaitForLoad(browser, "http://www.someurl.com", 1000);
   HtmlElement elemEmail = (HtmlElement)browser.Document.GetElementById("email");  
  }



 void NavigateAndWaitForLoad(WebBrowser wb, string link, int waitTime)  
  {  
   wb.Navigate(link);
   int count = 0;
   while (wb.ReadyState != WebBrowserReadyState.Complete)  
   {  
    Thread.Sleep(sleepTimeMiliseconds);
    Application.DoEvents();
    count++;
    if (count > waitTime / sleepTimeMiliseconds)
        break;  
    } 

シングル スレッドでは問題なく動作しますが、マルチスレッド アプリでは次の行でクラッシュします。
違法なキャスティングを除いて???!!!!
理由がわからない?
助けてください...

4

1 に答える 1

1

WebBrowser オブジェクト、Application.DoEvents、および Thread.Sleep を使用しています。悪い、悪い、悪い。あなたはここでトラブルを求めています。

提案:

Web クローラーを作成するだけの場合は、WebClientを使用して Web ページを文字列としてダウンロードします。次に、それを HTML ドキュメントに解析する必要がある場合は、HtmlAgilityPackを使用します。

このようにして、Web ブラウザーの UI コントロールの使用を避けることができ、Thread.Sleep の実行を避けることができ、偶発的な再帰を引き起こす Application.DoEvents を避けることができます。

サンプルは次のとおりです。

public async void DownloadWebPage(string address)
{
    using(var webClient = new WebClient())
    {
        var webPageContents = await webClient.DownloadStringTaskAsync();

        // Woohoo, we have the contents of the web page. Do anything with it...
        Console.WriteLine(webPageContents);
    }
}

// Usage:
DownloadWebPage("http://www.google.com");
于 2012-10-22T01:53:03.290 に答える