3

代码如下。

我正在尝试导航到网站并阅读信息,问题是导航不起作用,唯一调用的事件是导航并且打印的 Url 为空,其他事件永远不会被调用。我错过了什么?我必须使用 Form 类才能导航吗?我不能从控制台应用程序以编程方式使用它吗?

请帮忙。

class WebNavigator
{
    private readonly WebBrowser webBrowser;

    public WebNavigator()
    {
        webBrowser = new WebBrowser
        {
            AllowNavigation = true
        };

        webBrowser.Navigated += webBrowser_Navigated;
        webBrowser.Navigating += webBrowser_Navigating;
        webBrowser.DocumentCompleted += webBrowser_DocumentCompleted;
    }

    // Navigates to the given URL if it is valid. 
    public void Navigate(string address)
    {
        if (String.IsNullOrEmpty(address)) return;
        if (address.Equals("about:blank")) return;
        if (!address.StartsWith("http://") &&
            !address.StartsWith("https://"))
        {
            address = "http://" + address;
        }
        try
        {
            Trace.TraceInformation("Navigate to {0}", address);
            webBrowser.Navigate(new Uri(address));
        }
        catch (System.UriFormatException)
        {
            Trace.TraceError("Error");
            return;
        }
    }

    // Occurs when the WebBrowser control has navigated to a new document and has begun loading it.
    private void webBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
    {
        Trace.TraceInformation("Navigated to {0}", webBrowser.Url);
    }

    // Occurs before the WebBrowser control navigates to a new document.
    private void webBrowser_Navigating(object sender, WebBrowserNavigatingEventArgs e)
    {
        Trace.TraceInformation("Navigating to {0}", webBrowser.Url);
    }

    private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        var wb = sender as WebBrowser;
        Trace.TraceInformation("DocumentCompleted {0}", wb.Url);
    }
}
4

3 回答 3

6

我会使用await/async

用法:

static async void  DoWork()
{
    var html = await GetHtmlAsync("http://www.google.com/");
}

实用方法

static Task<string> GetHtmlAsync(string url)
{
    var tcs = new TaskCompletionSource<string>();

    var thread = new Thread(() =>
    {
        WebBrowser wb = new WebBrowser();

        WebBrowserDocumentCompletedEventHandler documentCompleted = null;
        documentCompleted = async (o, s) =>
        {
            wb.DocumentCompleted -= documentCompleted;
            await Task.Delay(2000); //Run JS a few seconds more

            tcs.TrySetResult(wb.DocumentText);
            wb.Dispose();
            Application.ExitThread();
        };

        wb.ScriptErrorsSuppressed = true;
        wb.DocumentCompleted += documentCompleted;
        wb.Navigate(url);
        Application.Run();
    });

    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();

    return tcs.Task;
}
于 2013-08-25T12:55:17.773 回答
1

感谢您的回答。通过添加这个包含 Application.DoEvents(); 的 while 子句解决了这个问题。

            webBrowser.Navigate(new Uri(address));
            while (!navigationCompleted)
            {
                Application.DoEvents();
                Thread.Sleep(navigationPollInterval);
            }

我不确定这是否是最好的解决方案,如果能听到更好的解决方案,我将不胜感激。

于 2013-08-25T12:52:32.923 回答
1

您提到这是一个控制台应用程序。要WebBrowser在控制台应用程序中工作,您需要确保浏览器的线程是 STA 线程 ( thread.SetApartmentState(ApartmentState.STA)。此外,为了能够处理事件,线程必须泵送消息 ( Application.Run)。考虑到这一点,您可能希望创建一个单独的线程(从您的主控制台线程)来运行 WebBrowser。

于 2013-08-25T12:38:33.050 回答