none
WebBrowserのNavigate処理中、発生するAccessViolationExceptionについて RRS feed

  • 質問

  • 現在 WebBrowserを使用してサイトページ情報を取得するプログラムを作成しています。

    特定のWebページをNavigateするとメモリーリークが発生し、そのまま
    同様のページを繰り返しNavigateし続けるとメモリ破壊が発生する。


    以下にサンプルプログラムを明示します。

    ~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~
      public partial class Form1 : Form
      {
          // ナビ完了フラグ
          private bool isDone;
          private string urlToNavi = "http://www2.victoriassecret.com/commerce/onlineProductDisplay.vs?namespace=productDisplay&origin=onlineProductDisplay.jsp&event=display&prnbr=EE-247484";

          public Form1()
          {
              InitializeComponent();

              this.webBrowser1.DocumentCompleted +=
                               new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);

              // ナビを繰り返すための無限ループ処理
              while (true)
              {
                  isDone = false;
                  NavigateAndWait();
              }
          }

          private void NavigateAndWait()
          {
              // Javascript技術が書き込まれているURLへナビ
              this.webBrowser1.Navigate(urlToNavi);
     
              // ナビが完了するまで待ち状態にする
              while (!isDone)
              {
                  Application.DoEvents();
              }
          }

          void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
          {
              // ナビが完了したら、ナビ完了フラグの値を変える
              if (e.Url == webBrowser1.Url)
              {
                  isDone = true;
              }
          }
      }
    ~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~・~


    このサンプルは、該当のページをNavigateし続けるプログラムです。
    ※本来は、類似ページをNavigateし続けます。

    該当のURL(urlToNavi)には高度な?Javascript技術が書き込まれていて
    Navigateした際に、JavaScriptエラーが発生しているようです。

    このサンプルを動かし続けると15分ほどで以下の例外が発生します。
    (発生場所:Application.DoEvents();)

    >「AccessViolationException はハンドルされませんでした。
    > 保護されているメモリに読み取りまたは書き込み操作を行おうとしました。
    > 他のメモリが壊れていることが考えられます。」


    本不具合について有効な対策&回避策などがありましたら、教えてください。

    ちなみに、以下はテストしたPCのスペックです。
    OS          : Microsoft Windows XP Professional SP3
    CPU         : Celeron CPU540 1.86GHz
    Memory      : 1GB
    IEバージョン: IE8

    お忙しいところ申し訳ありませんが、よろしくお願いいたします。

    2009年10月9日 8:31

回答

  • Form1 のコンストラクタに「ナビを繰り返すための無限ループ処理」を入れるのは間違いと思います。それから
    「ナビが完了するまで待ち状態にする」の while ループも不要で、これも問題ありそうです。 また、JavaScript
    は、今回の問題とは関係ないと思います。

    Navigate 繰り返すのであれば、ページの読み込みが終了したら、再度 Navigate することで可能なはずです。

    ただし、サンプルプログラムに記載されているページは iframe を2箇所で使っていて、全ページが表示されるま
    でに DocumentCompleted イベントが3回発生するのが問題です。

    このページに限れば、以下のようにすればうまくいくかも。でも、普通は DocumentCompleted イベントが3回も
    発生するページはないので、汎用的ではないのが問題ですが。

    namespace WebBrowserJavaScriptSite
    {
      
        public partial class Form1 : Form
        {
            private int count;
            private string urlToNavi = "http://www2.victoriassecret.com/commerce/onlineProductDisplay.vs?namespace=productDisplay&origin=onlineProductDisplay.jsp&event=display&prnbr=EE-247484";

            public Form1()
            {
                InitializeComponent();
                this.webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
                this.Load +=new EventHandler(Form1_Load);
            }

            private void Form1_Load(object sender, EventArgs e)
            {
                NavigateAndWait();
            }
            private void NavigateAndWait()
            {
                this.webBrowser1.Navigate(urlToNavi);
            }

            void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
            {
                count++;
                if (count > 2)
                {
                    count = 0;
                    System.Threading.Thread.Sleep(3000);
                    NavigateAndWait();
                }
            }
        }
    }

    • 回答としてマーク 菊地俊介 2009年10月29日 7:35
    2009年10月9日 13:31
  • > この現象は即ち、
    > メモリーリークの可能性を潜在していると思います。

    確かにメモリ使用量が時間とともに増えてくという現象は見られました。しかしながら、他の Web Site では
    そのような現象は見られませんでした。

    ちなみに、SHDocVw クラスを使用して IE8 を直接操作しても、メモリ使用量が時間とともに増えてくという現
    象は同じでした。まぁ、WebBrowser も IE のエンジンを使用しているそうなので、同じ結果になるのは当然か
    もしれませんけど。

    という訳で、原因がメモリーリークにあるのか、そのページ特有の現象なのか、それとも他に問題があるのかは
    自分には分かりません。

    正直言って、これ以上調べる気がせず、お役に立てずすみません。

    • 回答としてマーク 菊地俊介 2009年10月29日 7:35
    2009年10月14日 13:43

すべての返信

  • Form1 のコンストラクタに「ナビを繰り返すための無限ループ処理」を入れるのは間違いと思います。それから
    「ナビが完了するまで待ち状態にする」の while ループも不要で、これも問題ありそうです。 また、JavaScript
    は、今回の問題とは関係ないと思います。

    Navigate 繰り返すのであれば、ページの読み込みが終了したら、再度 Navigate することで可能なはずです。

    ただし、サンプルプログラムに記載されているページは iframe を2箇所で使っていて、全ページが表示されるま
    でに DocumentCompleted イベントが3回発生するのが問題です。

    このページに限れば、以下のようにすればうまくいくかも。でも、普通は DocumentCompleted イベントが3回も
    発生するページはないので、汎用的ではないのが問題ですが。

    namespace WebBrowserJavaScriptSite
    {
      
        public partial class Form1 : Form
        {
            private int count;
            private string urlToNavi = "http://www2.victoriassecret.com/commerce/onlineProductDisplay.vs?namespace=productDisplay&origin=onlineProductDisplay.jsp&event=display&prnbr=EE-247484";

            public Form1()
            {
                InitializeComponent();
                this.webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
                this.Load +=new EventHandler(Form1_Load);
            }

            private void Form1_Load(object sender, EventArgs e)
            {
                NavigateAndWait();
            }
            private void NavigateAndWait()
            {
                this.webBrowser1.Navigate(urlToNavi);
            }

            void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
            {
                count++;
                if (count > 2)
                {
                    count = 0;
                    System.Threading.Thread.Sleep(3000);
                    NavigateAndWait();
                }
            }
        }
    }

    • 回答としてマーク 菊地俊介 2009年10月29日 7:35
    2009年10月9日 13:31
  • SurferOnWwwさん、ご回答ありがとうございます。

    長時間テストを行ったため
    返事が遅れてしまいました。
    申し訳ございません。

    上記のソースで長時間テストしてみたところ、
    AccessViolationExceptionはもう発生してなかったのです。
    誠にありがとうございました。



    ちなみに、ちょっと別の問題について
    質問させて頂きたいと思います。

    WebBrowserを使ってNavigate()した場合は
    PCのメモリーがどんどん増える現象についてですが、

    タスクマネジャーを監視しながら、
    上記のサンプルで動かした場合にも
    メモリーが増えて最大メモリ使用量として
    700MBを超えています。

    この現象は即ち、
    メモリーリークの可能性を潜在していると思います。

    一応、手段としては以下のMicrosoftのSupportページを
    参考に対応しましたが、有効な結果は出てこなかったのです。

    http://support.microsoft.com/default.aspx/kb/943510/ja

    また、他に良い方法があればご教授ください。
    質問ばかりで恐縮です。

    以上、よろしくお願い致します。

    2009年10月13日 14:26
  • > この現象は即ち、
    > メモリーリークの可能性を潜在していると思います。

    確かにメモリ使用量が時間とともに増えてくという現象は見られました。しかしながら、他の Web Site では
    そのような現象は見られませんでした。

    ちなみに、SHDocVw クラスを使用して IE8 を直接操作しても、メモリ使用量が時間とともに増えてくという現
    象は同じでした。まぁ、WebBrowser も IE のエンジンを使用しているそうなので、同じ結果になるのは当然か
    もしれませんけど。

    という訳で、原因がメモリーリークにあるのか、そのページ特有の現象なのか、それとも他に問題があるのかは
    自分には分かりません。

    正直言って、これ以上調べる気がせず、お役に立てずすみません。

    • 回答としてマーク 菊地俊介 2009年10月29日 7:35
    2009年10月14日 13:43
  • SurferOnWwwさん。

    ご回答ありがとうございます。

    私の方でもAxWebBrowserを使ったり、
    IEのアドオン管理でActiveX機能を無効に設定したり試してみましたが、
    メモリーが増える現象は変わりませんでした。

    現段階ではSurferOnWwwさんの仰ったとおりに
    該当ページ特有の問題(Javascript機能)だと思われます。

    >お役に立てずすみません。

    いいえ、お蔭様で良い勉強になりました。
    ありがとうございました。 <(_ _)>
    2009年10月15日 1:05
  • 皆様、こんにちは。

    SurferOnWwwさん、サンプルコードつきの詳しい回答、ありがとうございます。

    tristan28さん、フォーラムのご利用ありがとうございます。
    有用な情報と思われたため、SurferOnWwwさんの回答へ回答マークをつけさせていただきました。

    参考までに、JavaScript に関するツールを紹介させていただきます。
    JavaScript Memory Leak Detector (v2)
    http://blogs.msdn.com/gpde/pages/javascript-memory-leak-detector-v2.aspx

    今後ともフォーラムをよろしくお願いします。
    それでは!
    2009年10月29日 7:46