WebBrowser.Navigated は、MessageBox.Show(); の場合にのみ起動します。
-
21-08-2019 - |
質問
親スレッドはBackgroundWorkerであり、他にやるべきことがたくさんあるため、バックグラウンドSTAスレッドから動的にインスタンス化されているWebBrowserコントロールがあります。
問題は、.Navigate() を指示するメソッドで MessageBox.Show() をポップしない限り、Navigated イベントが決して起動しないことです。説明します:
ThreadStart ts = new ThreadStart(GetLandingPageContent_ChildThread);
Thread t = new Thread(ts);
t.SetApartmentState(ApartmentState.STA);
t.Name = "Mailbox Processor";
t.Start();
protected void GetLandingPageContent_ChildThread()
{
WebBrowser wb = new WebBrowser();
wb.Navigated += new WebBrowserNavigatedEventHandler(wb_Navigated);
wb.Navigate(_url);
MessageBox.Show("W00t");
}
protected void wb_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
WebBrowser wb = (WebBrowser)sender; // Breakpoint
HtmlDocument hDoc = wb.Document;
}
これはうまくいきます。ただし、これは自動化アプリであるため、メッセージボックスが邪魔になります。MessageBox.Show() を削除すると、WebBrowser.Navigated イベントが発生しません。この行を Thread.Sleep() に置き換え、親スレッドを一時停止してみました。
これを解決したら、WebBrowser がそのジョブを実行している間に親スレッドを一時停止し、結果の HTML を親スレッドに渡す何らかの方法を見つけて、親スレッドがさらなるロジックを続行できるようにするつもりです。
なぜこのようなことをするのでしょうか?どうすれば修正できますか?
POST 動詞もサポートしていない Web サーバーに対して、Web ページのコンテンツを取得し、データを入力し、送信ボタンの反対側にページのコンテンツを返す方法を誰かが提供してくれたらどうでしょうか。 QueryString を介してデータを渡す場合、この演習全体が不要になるため、その答えも受け入れます。
解決: 結局、チームアーキテクトの提案により、BackgroundWorker とスレーブ スレッドをまったく使用しなくなりました...ただし、応答性は犠牲になります:(
解決
WebBrowser
表示され、UI スレッドが関連付けられていない限り、あまり機能しません。それが存在するフォームを表示していますか?DOMなどを使用するには必要です。ユーザーにフォームを表示したくない場合は、フォームを画面外に表示することもできますが、(たとえば) サービスではうまく機能しません。
スクレイピング目的の場合、通常は次を使用して通常の HTML ブラウザをシミュレートできます。 WebClient
等これでは十分ではないでしょうか?「」のようなツールを使用できます。バイオリン弾き」を使用して、サーバーに対して行う必要がある正確なリクエストを調査します。それ以上については、以下を参照してください。 HTML アジリティ パック, 、ブラウザを使わずに HTML への DOM アクセスを提供します。
他のヒント
WebBrowser の可視性が false に設定されている場合、Navigated イベントと DocumentComplete イベントは発生しません。この制限を回避するには、次のように WebBrowser を表示し、その場所をユーザー インターフェイスの外側に設定します。
wb.Visible = true;
wb.Left = -wb.Width; // notice the minus sign
次のような行を追加する必要があります。
webBrowser1.Navigated += new WebBrowserNavigatedEventHandler(webBrowser1_Navigated);
どこ webBrowswer1_Navigated
イベントの発生時に呼び出す関数です。
すでに開始されている GUI スレッドはありますか?おそらく、WebBrowser オブジェクトは GUI スレッドを使用してイベントを処理します。その場合は、WebBrowser を作成するスレッドから Application.Run() を呼び出す必要があります (MessageBox.Show() をこれに置き換えます)。Application.Run() は、Application.Exit() が呼び出されるまでハングします。
今これをテストしようとしています。
結局、チームアーキテクトの提案により、BackgroundWorker とスレーブ スレッドをまったく使用しなくなりました...ただし、応答性は犠牲になります:(
WebBrowser コントロールは、STA スレッド内にない場合は機能しません。スレッドで WebBrowser インスタンスを使用したい場合は、スレッドを作成して呼び出す必要があります。 Thread.SetApartmentState(ApartmentState.STA);