WebBrowser控件抛出看似随机的NullReferenceException

本文关键字:随机 NullReferenceException 控件 WebBrowser | 更新日期: 2023-09-27 18:10:45

几天来我一直在做一个基于WebBrowser的webscraper。在用Threads和DocumentCompleted事件做了几个原型之后,我决定试着看看我是否能做一个简单、容易理解的Webscraper。

目标是创建一个不涉及实际线程对象的Webscraper。我希望它的工作顺序的步骤(即转到url,执行动作,转到其他url等)。

这是我目前得到的:

public static class Webscraper
{
    private static WebBrowser _wb;
    public static string URL;
    //WebBrowser objects have to run in Single Thread Appartment for some reason.
    [STAThread] 
    public static void Init_Browser()
    { 
        _wb = new WebBrowser();
    }

    public static void Navigate_And_Wait(string url)
    {
        //Navigate to a specific url.
        _wb.Navigate(url);
        //Wait till the url is loaded.
        while (_wb.IsBusy) ;
        //Loop until current url == target url. (In case a website loads urls in steps)
        while (!_wb.Url.ToString().Contains(url))
        {
            //Wait till next url is loaded
            while (_wb.IsBusy) ;
        }
        //Place URL
        URL = _wb.Url.ToString();
    }
}

我是一个新手程序员,但我认为这是相当简单的代码。这就是为什么我讨厌程序在这段代码中抛出NullReferenceException的原因:

 _wb.Url.ToString().Contains(url)

我刚刚调用了_wb. navigate()方法,所以NullReference不能在_wb对象本身中。所以我唯一能想到的就是_wb。Url对象为空。但是while _wb.IsBusy()循环应该可以防止这种情况。

那么发生了什么,我该如何解决它?

WebBrowser控件抛出看似随机的NullReferenceException

在UI线程上忙于等待(while (_wb.IsBusy) ;)是不太可取的。如果你使用。net 4.5的新特性async/await,你可以得到类似的效果(即。转到url,执行操作,转到其他url等等,等等)你想要

public static class SOExtensions
{
    public static Task NavigateAsync(this WebBrowser wb, string url)
    {
        TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
        WebBrowserDocumentCompletedEventHandler completedEvent = null;
        completedEvent = (sender, e) =>
        {
            wb.DocumentCompleted -= completedEvent;
            tcs.SetResult(null);
        };
        wb.DocumentCompleted += completedEvent;
        wb.ScriptErrorsSuppressed = true;
        wb.Navigate(url);
        return tcs.Task;
    }
}

async void ProcessButtonClick()
{
    await webBrowser1.NavigateAsync("http://www.stackoverflow.com");
    MessageBox.Show(webBrowser1.DocumentTitle);
    await webBrowser1.NavigateAsync("http://www.google.com");
    MessageBox.Show(webBrowser1.DocumentTitle);
}