2012-10-21 36 views
2

到目前为止,我有一个单线程的应用程序爬行网站。
因为我想让它更快,所以我尝试重建到多线程应用程序。 这就是我所做的:
我有一个Crawl Class,它拥有一个WebBrowser对象。 这是我如何启动线程:Web浏览器MultiThreded Casting异常

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; 
    } 

现在在单线程它的伟大工程, 然而在mutlithreded应用程序崩溃在这一行: HtmlElement elemEmail =(HtmlElement)browser.Document.GetElementById(“email”);
除非法铸造??? !!!
不知道为什么?
请帮助...

+0

非法铸造?以及'browser.Document.GetElementById(“email”)''的实际类型是什么?你可以在调试器中查找吗? – Vlad

+0

它的类型是HtmlElement – user1763180

+0

不错,那么投不应该失败吧? – Vlad

回答

1

您正在使用WebBrowser对象Application.DoEvents和Thread.Sleep。坏,坏,坏。你在这里要求麻烦。

建议:

如果你只是建立一个网络爬虫,只要使用WebClient下载网页作为一个字符串。然后,如果您需要将其解析为HTML文档,请使用HtmlAgilityPack

这样可以避免使用网页浏览器的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");