- - PR -
Form上のコントロールのDispose()について
1|2|3
次のページへ»
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-09-25 19:03
Compact Framework 2.0環境での話です。
OSはWindows CE 5.0です。 作成したFormアプリケーションを使用しているとOutOfMemoryExceptionが発生することがあります。 調査した結果、画面遷移を繰り返すと発生するらしいということで、以下のようなテストアプリケーションを作成してみました。 Form1がForm2を延々呼び出しては破棄する、という内容です。 ----Form1.cs---- public partial class Form1 : Form { private void button1_Click(object sender, EventArgs e) { while (true) { Form2 fm2 = new Form2(); fm2.ShowDialog(); fm2.Dispose(); GC.Collect(); } } } ----Form2.cs---- // Form2には120個くらいのComboBox(メモリ消費を早くするため)を貼り付けています。 public partial class Form2 : Form { // TimerによりTickイベント発生→画面を閉じる。 private void timer1_Tick(object sender, EventArgs e) { this.Close(); } } 上記コードで試してみたところ、メモリ消費量は徐々に増加していきました。 (コンパネのメモリから確認しただけですが、Collect()しているからCollect対象外のメモリサイズを見ているのと「≒」かなと) それで、いろいろと考えた挙句、次のようにDispose()内に、画面上の全コントロールに対してDispose()を発行してみたところ、メモリ増加する現象が改善されることが確認できました。 ----Form2.Designer.cs---- protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } // ここで全ComboBoxに対してDispose()を実行 comboBox1.Dispose(); // ←ここを追加 comboBox2.Dispose(); // ←ここを追加 : // ←ここを追加 : // ←ここを追加 base.Dispose(disposing); } ここで皆様のご意見をいただきたいのです。 @こういったコーディングで解決するのは一般的なのでしょうか? Aもしくはこういったコーディングは必須なのでしょうか? B他によい方法はないでしょうか? #WinCEOS搭載のデバイスということで、使用可能なメモリが小さいという制約があるのと、長時間アプリケーションが終了することがないため、メモリ管理に気を使っています。 #http://msdn.microsoft.com/ja-jp/library/fs2xkftw(VS.80).aspx あたりも見てみましたが、サンプルではアンマネージなリソースを解放する例はありますが、フォーム上のコントロールまで破棄するサンプルというのを見たことがないので、どうしたものか悩んでいます。コントロールはComponent継承なのでIDisposableだから当然必要な対処なんだろうか、とか。。。悶々。 よろしくお願いします。 | ||||||||||||
|
投稿日時: 2008-09-25 22:09
この辺を探していただければ、その手の話題はゴロゴロしています。
1.一般的ではない。 2.必須ではない。 3.他のことでメモリを消費していると思われます。BCL を疑うより、ご自分のプログラムを疑う方が先かと思います。
コンテナ コントロールに所属するコントロールは、コンテナ コントロールの Dispose メソッド内で Dispose するため、不要です。Controls プロパティによって、所属するコントロールにアクセスできます。一つ一つ、コントロールを列挙しなくても、Controls プロパティを列挙すれば済みます。 詳しいことは、 囚人さん blogs.wankuma.com/shuujin/ 菊池さん www.ailight.jp/blog/kazuk/ NyaRuRuさん d.hatena.ne.jp/NyaRuRu/ のところを検索すれば見つかるでしょう。「dispose site:blogs.wankuma.com/shujin」 | ||||||||||||
|
投稿日時: 2008-09-30 16:57
Windows CE 5.0の.NET Framework 2.0(C#)で、
同様の問題ではまったことがあります。 悪い例: Form form = new HogeForm(); form.ShowDialog(); form.Dispose(); 良い例: Form form = new HogeForm(); form.ShowDialog(); form.Dispose(); form = null; 最後にnullを設定しないと、このフォームがガベージコレクトされず、 メモリリークします。 Microsoftのサポートに問い合わせて回答をもらいましたので、 確かですが、そちらの環境の原因と同じかどうかはわかりません。 とりあえず試してみてください。 #…と同じ内容をslashdotでも投稿しました | ||||||||||||
|
投稿日時: 2008-09-30 19:39
はつみみです。 参照の解放でガベージコレクトのされやすさを期待できるならともかく、まったくガベージコレクトされず "メモリリーク" するなんてことはないと思うのですが... しかも 2.0 で、ですか... '広域な変数でかつリソースを食っている変数' など、もっと限定的な状況のお話ではないのでしょうか? 本当の話であれば私の作ったアプリケーション全滅w
_________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||||||
|
投稿日時: 2008-09-30 21:32
とりあえず、
.net framework 2.0 gc compact site:support.microsoft.com では、該当するものは出てきませんでした。 | ||||||||||||
|
投稿日時: 2008-10-01 13:29
私が書いたメモリリークの件ですが、現象が出るのはFormクラスだけです。
他のクラスでは問題ないようです。 限定的な話なのかもしれませんが、Microsoftの有償サポートに 問い合わせたところ、Microsoft側でも「現象を確認した」との返事が ありましたので、やっぱり確かなんだと思います。 現象が発生した環境は、 SHARP RZ-1501 Windows CE v5.00 Build1400 On Aug 28 2006 Visual Studio 2005 SP1 Microsoft .NET Compact Framework 2.0 SP1 です。 逆に、他の環境でも現象が再現するか試して頂けると助かります。 ボタンがいくつかあるだけのFormを作り、 (a) ShowDialogとDisposeをひたすら繰り返す (b) ShowDialogとDisposeとnull設定をひたすら繰り返す プログラムで、メモリの減り具合を観察してみてください。 | ||||||||||||
|
投稿日時: 2008-10-01 21:04
しまつた。。。改善されるのは当たり前じゃないか。 IDisposable インターフェイスで、「管理しなければならないものがある」ことを示したとき、管理を行うのは開発者です。対して、GC によって管理されるメモリは、GC が管理するので、開発者は管理できません。 それをおさえて、このコードをよく見て、よく考えよう。改善されるのは当たり前です。 で、何が間違っているかというと、GC.Colect をしていること。このコードに関しては、よしもさんが書かれている通り、GC.Colect の前で、null 参照してやる必要があります。これは正しい仕様で、その通り実装されているので、バグではありません。 改善される理由: Dispose が引数付きであることに注目して下さい。その引数は、どんなときに、どんな値になるでしょうか。 しかし、fm2.Dispose() と、引数なしで実行しています。どうしてでしょう? バグではない理由: 参照していると、回収されません。Dispose は、メモリの破棄ではありません。 | ||||||||||||
|
投稿日時: 2008-10-01 21:25
すみません
引数の方は、勘違いです。 |
1|2|3
次のページへ»