2012-10-21 37 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");