DOBON.NET DOBON.NETプログラミング掲示板過去ログ

webBrowser1_DocumentCompletedでの取りこぼし

環境/言語:[win7 visual studio 2008 c#]
分類:[.NET]

パソコン内のHTMLファイルをwebBrowser1.Navigateで表示しています。
サイト表示完了後に各種ボタンを有効にしています。

ほとんどのHTMLファイルは DocumentCompleted イベントで表示完了が確認できます。

しかし、すぐに表示される(いわゆる軽いページ)の場合、イベントが発生しないようです。
そのためエンドレスに待機してしまいます。

タイマーを設置することも考えましたが、逆に重いページの場合は、
表示が完了する前にボタンが有効になってしまう可能性があります。

メインのコードは次のようになっています。

  bool BL待機 = true;
  webBrowser1.Navigate( htmlファイル );
  while (BL待機)  //webBrowser1_DocumentCompletedでfalseにする
  {
    Application.DoEvents();
  }

Application.DoEvents();で待つことも本当は避けたいのですが…。

webBrowser1_DocumentCompletedで確実に拾う方法、
または代替案がありましたら、よろしくお願いします。
■No27873に返信(duke0045さんの記事)
> ほとんどのHTMLファイルは DocumentCompleted イベントで表示完了が確認できます。
「フレームを使ったサイト」「リダイレクトが発生するサイト」などでは、
DocumentCompleted が複数回発生する事がありますので、どのタイミングの
イベントを用いるかも考慮する必要がありますね。

> しかし、すぐに表示される(いわゆる軽いページ)の場合、
具体的には、どの URL ですか?

> そのためエンドレスに待機してしまいます。
タイムアウトさせてみては如何でしょう。
たとえば Timer 等を併用して、一定時間待ってもイベントが発生しない場合、
DocumentCompleted を待たずに webBrowser1.Document を受け取るようにするとか。

> タイマーを設置することも考えましたが、逆に重いページの場合は、
> 表示が完了する前にボタンが有効になってしまう可能性があります。
タイムアウト判定時に、IsBusy 判定を行い、まだ読み込んでいるようなら、
タイムアウト時間を延長するようにしてみるとか。

> while (BL待機) //webBrowser1_DocumentCompletedでfalseにする
何故、DoEvents 待機しているのでしょうか?
Navigate した後、何もせずに return するだけで良いと思いますが…。

> Application.DoEvents();で待つことも本当は避けたいのですが…。
避けましょうよ。(^_^;)

「CheckBox が変更された時に処理を行う」というコードを
下記のように書いたりはしませんよね…?

 while ( Check待機) // checkBox1_CheckedChanged イベントでfalseにする
 {
 Application.DoEvents();
 }
魔界の仮面弁士さま、ありがとうございます。

タイマーを設置して、ビジーの場合は延長すると言う方法を採用しました。
予定通りの動作をしています。
ありがとうございます。

Application.DoEvents();は、これがないとwhileをループし続けてしまいます。

本来的には、Navigateしてから待つのではなく、
timer1とDocumentCompletedのイベントでコントロールするべきですね。

DoEventsを使わなくても良いようにコードを見直してみます。


BL待機 = true;

if( strファイル名 != "" ){
webBrowser1.ScriptErrorsSuppressed = false;
webBrowser1.Visible = 表示;
webBrowser1.Navigate( strファイル名 );

timer1.Interval = 5*1000;//5秒待機
timer1.Enabled = true;

//待機
while (BL待機)//webBrowser1_DocumentCompletedでfalseにする
{
Application.DoEvents();
}
timer1.Enabled = false;
}

private void timer1_Tick(object sender, EventArgs e)
{
if (webBrowser1.IsBusy == false) BL待機 = false;
}
■No27876に返信(duke0045さんの記事)
> Application.DoEvents();は、これがないとwhileをループし続けてしまいます。
そうではなくて、そもそもループするべきではない、と言う意味です。

現状の処理が
 void button1_Click(…)
 {
  処理1(); // Navigate 等
  while(flg) { Application.DoEvents(); }
  処理2();
 }
なのであれば、それを
 void button1_Click(…)
 {
  処理1(); // Navigate 等
 }
 void webBrowser1_DocumentComplted(…)
 {
  処理2();
 }
とすれば済むように思うのですが…。


> 本来的には、Navigateしてから待つのではなく、
> timer1とDocumentCompletedのイベントでコントロールするべきですね。
ですね。WebBrowser に限った話では無いですが、イベント駆動型の
処理実装を行うべき箇所で、DoEvents ループを使うのは無理があります。

イベントを取りこぼしたのも、余計な待機処理を行ったことが
原因になっているのでは無いでしょうか。
通常の利用では「軽いページ」であってもイベントは発生するはずです。

# リロード時のように、イベントが呼ばれないケースも無いわけではないですが。
魔界の仮面弁士さま

ありがとうございます。
今後は設計時点で、この点を考慮していきます。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板