3

以下のコード。

Web サイトに移動して情報を読み取ろうとしていますが、問題は Navigate が機能しないことです。呼び出されるイベントは Navigating のみで、印刷された 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 に答える