C# WebBrowser控件引发看似随机的NullReferenceException

C# WebBrowser控件引发看似随机的NullReferenceException,c#,winforms,exception-handling,webbrowser-control,nullreferenceexception,C#,Winforms,Exception Handling,Webbrowser Control,Nullreferenceexception,几天来,我一直在开发基于WebBrowser的webscraper。在使用线程和文档完成事件的两个原型之后,我决定尝试制作一个简单易懂的Webscraper 目标是创建一个不涉及实际线程对象的Webscraper。我希望它能按顺序工作(即转到url、执行操作、转到其他url等) 到目前为止,我得到的是: public static class Webscraper { private static WebBrowser _wb; public static string URL;

几天来,我一直在开发基于WebBrowser的webscraper。在使用线程和文档完成事件的两个原型之后,我决定尝试制作一个简单易懂的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\u wb.IsBusy()循环应该可以防止这种情况

那么到底发生了什么以及如何修复它呢?

在UI线程上忙着等待(
而(\u wb.IsBusy);
)是不可取的。如果您使用.Net 4.5的新功能,您可以获得类似的效果(即转到url、执行操作、转到其他url等)

公共静态类SOExtensions
{
公共静态任务NavigateAsync(此WebBrowser wb,字符串url)
{
TaskCompletionSource tcs=新的TaskCompletionSource();
WebBrowserDocumentCompletedEventHandler completedEvent=null;
completedEvent=(发送方,e)=>
{
wb.DocumentCompleted-=已完成事件;
tcs.SetResult(空);
};
wb.DocumentCompleted+=已完成事件;
wb.ScriptErrorsSuppressed=true;
wb.Navigate(url);
返回tcs.Task;
}
}
异步void ProcessButtonClick()
{
等待webBrowser1.NavigateAsync(“http://www.stackoverflow.com");
MessageBox.Show(webBrowser1.DocumentTitle);
等待webBrowser1.NavigateAsync(“http://www.google.com");
MessageBox.Show(webBrowser1.DocumentTitle);
}

在我使用.Net 4.0的那一刻,但这看起来确实是我需要的东西。
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);
}