2

到目前为止,我有一个抓取网站的单线程应用程序。
因为我想让它更快,我尝试重建为一个多线程应用程序。这就是我所做的:
我有一个 Crawl 类,它包含一个 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;  
    } 

现在在单线程中它工作得很好,但是在多线程应用程序中它在这一行崩溃: HtmlElement elemEmail = (HtmlElement)browser.Document.GetElementById("email");
非法铸造除外???!!!
不知道为什么?
请帮忙...

4

1 回答 1

1

您正在使用 WebBrowser 对象、Application.DoEvents 和 Thread.Sleep。糟糕,糟糕,糟糕。你在这里自找麻烦。

建议:

如果您只是构建一个网络爬虫,只需使用WebClient将网页作为字符串下载。然后,如果您需要将其解析为 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 回答