none
動的に生成したコントロールのリソース解放について RRS feed

  • 質問

  • お世話になっております。kinji01と申します。

     

    現在作成中のある画面で「ウィンドウのハンドルを作成中にエラーが発生しました。」という

    例外が発生してしまい、なおかつそれを解決することができません。

     

    この画面では、配列をつかってLabelコントロール(およびLabelを継承した独自コントロール)を

    動的に生成してPanel上のコントロールとし、それらにAddHandlerでイベントとプロシージャを

    関連付けて動作をさせています。

    画面をクリアする際に全ての動的生成コントロールをPanelからクリアし、RemoveHandlerで

    関連付けを解除した後Nothingを代入し、最後にコントロールの配列をRedimすることで

    リソースを解放できているつもりでした。

    しかし何度か表示、クリアを繰り返していると表示処理中に上記の例外が発生してしまいます。

    現象とエラーの内容からどうやらリソースの解放ができていないようであると考えました。

     

    自分なりに調査をしたりテストをしたりしているのですが、一向に状況が改善されません。

    何がいけないのかご指摘していただければ幸いです。

     

    なお環境は以下の通りです。

     

    OS:WIndows XP Professional

    開発環境:VB2005

     

    よろしくお願いいたします。

     

    参考までに例外発生時のスタックトレースを以下に記載します。

     

       場所 System.Windows.Forms.Control.SetAcceptDrops(Boolean accept)
       場所 System.Windows.Forms.Control.OnHandleCreated(EventArgs e)
       場所 System.Windows.Forms.Control.WmCreate(Message& m)
       場所 System.Windows.Forms.Control.WndProc(Message& m)
       場所 System.Windows.Forms.Label.WndProc(Message& m)
       場所 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       場所 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       場所 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       場所 System.Windows.Forms.UnsafeNativeMethods.IntCreateWindowEx(Int32 dwExStyle, String lpszClassName, String lpszWindowName, Int32 style, Int32 x, Int32 y, Int32 width, Int32 height, HandleRef hWndParent, HandleRef hMenu, HandleRef hInst, Object pvParam)
       場所 System.Windows.Forms.UnsafeNativeMethods.CreateWindowEx(Int32 dwExStyle, String lpszClassName, String lpszWindowName, Int32 style, Int32 x, Int32 y, Int32 width, Int32 height, HandleRef hWndParent, HandleRef hMenu, HandleRef hInst, Object pvParam)
       場所 System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp)
       場所 System.Windows.Forms.Control.CreateHandle()
       場所 System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
       場所 System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
       場所 System.Windows.Forms.Control.CreateControl()
       場所 System.Windows.Forms.Control.ControlCollection.Add(Control value)
       場所 System.Windows.Forms.Control.set_ParentInternal(Control value)
       場所 System.Windows.Forms.Control.set_Parent(Control value)

    2007年9月26日 9:32

回答

  • disposeすれば、回避できるでしょうけど、参照が残っているとdisposeされたオブジェクトにアクセスできません、

    みたいなメッセージがでる可能性があります。

     

    ともかく、作成時と開放時のソースコードを見せてもらいたいです。

     

    2007年9月26日 12:10

すべての返信

  • disposeすれば、回避できるでしょうけど、参照が残っているとdisposeされたオブジェクトにアクセスできません、

    みたいなメッセージがでる可能性があります。

     

    ともかく、作成時と開放時のソースコードを見せてもらいたいです。

     

    2007年9月26日 12:10
  • はなはなはなさんありがとうございます。

     

    > ともかく、作成時と開放時のソースコードを見せてもらいたいです。

     

    作成時および解放時のソースを記載します。

    そのまんまではなくある程度省略しますが、生成、解放の手順には一切省略はありません。

     

    作成時

     

                For i = 0 To ds.Count - 1
                    ReDim Preserve lblBack(i)

                    lblBack(i) = New Label
                    'クリックイベント
                    AddHandler lblBack(i).Click, AddressOf Me.lblBack_Click
                Next
                pnlPage.Controls.AddRange(lblBack)

     

     

     

    解放時

            pnlPage.Controls.Clear()
            For i = 0 To lblBack.Length - 1
                'クリックイベント
                RemoveHandler lblBack(i).Click, AddressOf Me.lblBack_Click
                lblBack(i) = Nothing
            Next

            ReDim lblBack(0)

     

     

     

     

    > disposeすれば、回避できるでしょうけど、参照が残っているとdisposeされたオブジェクトにアクセスできません、

    > みたいなメッセージがでる可能性があります。

     

    なぜかDisposeが抜けていたことにご指摘を受けてやっと気がつきました。

    さっそく解放時にラベルのDisposeメソッドを実行させるようにしてテストしてみました。

    結果は、修正前は5回でエラーになっていたところが10回以上の表示、クリアを行っても

    エラーにならないようになりました。

     

    今はまだとりあえずですが、もっとテストを重ねてそれでも大丈夫ならこれでいこうかと思います。

    どうもありがとうございました。

    2007年9月26日 13:33