- PR -

Formを閉じる際のリソース解放について

投稿者投稿内容
ベテラン
会議室デビュー日: 2005/05/16
投稿数: 85
お住まい・勤務地: 千葉県在住
投稿日時: 2006-07-06 19:36
いつもお世話になっております。
初歩的な質問かもしれませんが、どうかお付き合い下さい。

環境は、VS.NET2003のC#で作成したWindowsアプリです。

あるフォームのLoadイベント内で、自作Classのインスタンスを作成しています。
このClassはIDisposableを実装していないため、フォームのClosedイベントで
Disposeする事も無く、現在はnullもセットしていません。

Classの役割は構造体に毛が生えたようなもので、Class変数を幾つか所持しています。
但し、フォームからの要求でDBからデータを取得し、自らが保持する変数に値を
セットし、フォームはClassの保持している変数の値を参照しています。

このようなClassの使用方法の場合、やはりIDisposableを実装して、
フォームが閉じられるタイミングでDisposeするべきなのでしょうか?
あるいは、IDisposableを実装しなくても、インスタンスにnullをセットすれば
参照が消えて、後はGCが勝手に解放してくれるものなのでしょうか?

基本的にフォーム内で作成されたインスタンスは、フォームが閉じられたタイミングで
あたかもメソッド内のローカル変数が破棄されるように、インスタンスも勝手に
破棄されるものと思っていたので、現在は何もしていないのですが・・・

ご意見、ご指摘など、宜しくお願い致します。
かるあ
ぬし
会議室デビュー日: 2003/11/16
投稿数: 1190
お住まい・勤務地: センガワ→ムサシノ
投稿日時: 2006-07-06 19:44
特に null をセットする必要もないんじゃですかね、
すぐに開放したいアンマネージリソースを内部に保持しているのでなければ
dispose を実装する必要もないです。

ですので、気になるのはこの部分
引用:

梶さんの書き込み (2006-07-06 19:36) より:

但し、フォームからの要求でDBからデータを取得し、自らが保持する変数に値を
セットし、フォームはClassの保持している変数の値を参照しています。


DBのコネクションはしっかり破棄できていますか?
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-07-06 19:48
引用:

梶さんの書き込み (2006-07-06 19:36) より:

このようなClassの使用方法の場合、やはりIDisposableを実装して、
フォームが閉じられるタイミングでDisposeするべきなのでしょうか?


そのクラスの '何' を、Dispose したいのでしょうか?
投稿された内容からは、それがわからないです。

引用:

Classの役割は構造体に毛が生えたようなもので、Class変数を幾つか所持しています。
但し、フォームからの要求でDBからデータを取得し、自らが保持する変数に値を
セットし、フォームはClassの保持している変数の値を参照しています。


この説明を見るに、そのクラスは、'解放しなくてはならないリソース' を持っていないように思えます。

引用:

あるいは、IDisposableを実装しなくても、インスタンスにnullをセットすれば
参照が消えて、後はGCが勝手に解放してくれるものなのでしょうか?


(先の説明を前提に考えますと)
参照を解放しなくとも未到達になれば、そのうち GC が回収してくれます。

# すみません、ちょっと被りました。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2006-07-06 21:08
IDisposable を実装しなければならないのは何故だと考えていますか?
どうやらマネージリソースとアンマネージリソースの区別なく IDisposable の実装が必要であると考えておられるようですが、IDisposable を実装すべきなのは、アンマネージリソースの開放が必要な場合だけです。

引用:

あるいは、IDisposableを実装しなくても、インスタンスにnullをセットすれば
参照が消えて、後はGCが勝手に解放してくれるものなのでしょうか?


はい。IDisposable とインスタンスが所有しているメモリは関係ありません。

_________________
囚人のジレンマな日々
ベテラン
会議室デビュー日: 2005/05/16
投稿数: 85
お住まい・勤務地: 千葉県在住
投稿日時: 2006-07-07 09:12
かるあさん。じゃんぬねっとさん。囚人さん。
早速のご回答ありがとうございます。

引用:

じゃんぬねっとさんの書き込み (2006-07-06 19:48) より:
そのクラスの '何' を、Dispose したいのでしょうか?
投稿された内容からは、それがわからないです。



実はつい最近納品したアプリで、同じ処理(画面を開き再登録して画面を閉じる等)を
繰り返していくと使用メモリがどんどん増加して、300MBを越えたあたりから
パフォーマンスが低下する。これはメモリリークを起こしているんだろう・・・
的な事を指摘されてしまいまして。
それで、ソースを確認してみたら、自分で作ったClassは確かに破棄してないなと
まさかこれが、メモリリークの原因になってたりしてないかな?と思い
質問を投げさせて頂きました。

引用:

囚人さんの書き込み (2006-07-06 21:08) より:
IDisposable を実装しなければならないのは何故だと考えていますか?



自分自身、まだマネージリソースとアンマネージリソースの違いが良く判っていない
という事もあり、また、元請け会社の方からは、ここのURLのチェックシートを全部
チェックしろ等と言われ、かなり混乱している状況です。
http://www.microsoft.com/japan/msdn/enterprise/pag/scalenetcheck06.asp

引用:

かるあさんの書き込み (2006-07-06 19:44) より:
DBのコネクションはしっかり破棄できていますか?



今回のアプリはリモーティングを使用した3階層で、コネクションの接続・切断等は
全てサーバーアプリ側に実装しており、破棄などもきちんとしております。


皆さんのご指摘を元に、再度ソースの見直しをしようと思います。
他に何か気を付けたほうが良いこと等ありましたら、ご意見下さい。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-07-07 09:30
引用:

梶さんの書き込み (2006-07-07 09:12) より:

実はつい最近納品したアプリで、同じ処理(画面を開き再登録して画面を閉じる等)を
繰り返していくと使用メモリがどんどん増加して、300MBを越えたあたりからパフォーマンスが低下する。これはメモリリークを起こしているんだろう・・・的な事を指摘されてしまいまして。


だからといって、なぜ先ほどあげたクラスを疑ったのでしょうか?
もっと別の場所を疑うべきではないのでしょうか?

それと、本当に限りなく使用メモリが増えていますか?
どこかで増加が止まったりしていませんか?

引用:

それで、ソースを確認してみたら、自分で作ったClassは確かに破棄してないなとまさかこれが、メモリリークの原因になってたりしてないかな?と思い質問を投げさせて頂きました。


説明されたものがすべてだとすると、原因になることはないでしょう。

引用:

今回のアプリはリモーティングを使用した3階層で、コネクションの接続・切断等は
全てサーバーアプリ側に実装しており、破棄などもきちんとしております。


まあ、それでも再確認の余地はありますね。
私はそのソースを見れるわけではないので、そう思ってしまうだけかもしれませんが...

原因だと疑う箇所があれば、ミニマムコードを作成して本当にそこが原因か確認はできますよね?
いずれにせよ、原因を確定させるには '実証しなくてはいけない' と思います。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
ベテラン
会議室デビュー日: 2005/05/16
投稿数: 85
お住まい・勤務地: 千葉県在住
投稿日時: 2006-07-07 13:38
引用:

じゃんぬねっとさんの書き込み (2006-07-07 09:30) より:
だからといって、なぜ先ほどあげたクラスを疑ったのでしょうか?
もっと別の場所を疑うべきではないのでしょうか?



先ずは、解放のタイミングが怪しいクラスやフォームの変数から
疑ってみようと思って調べたところ、明示的に破棄していない
クラスのインスタンスがあったので、大丈夫なのかな?と思い
こちらに質問させて頂きました。

引用:

それと、本当に限りなく使用メモリが増えていますか?
どこかで増加が止まったりしていませんか?


引用:

いずれにせよ、原因を確定させるには '実証しなくてはいけない' と思います。



取り敢えず、問題の画面に対し、開く→データ取得→データ再登録→閉じる
のサイクルを延々繰り返し手見ました。
アプリの使用メモリは40,132kbからスタートし、1サイクルで大体600kほど
メモリが増加します。
300サイクル繰り返したところメモリ使用量は258,372kb。
310サイクル目から、画面を開くとフォーム内のチェックボックス部分の表示が
何故か白地に赤枠バッテンの表示になってしまいました。

現在は、各メソッド・イベント内で解放忘れのリソースが無いか調査しており、
メソッドのローカルに作成したDataSetやDataTableがDisposeされていない場所が、
何箇所か見つかりました。

取り敢えずは、これらにDispose+nullセットを施そうと考えています。

ちなみに・・・
DataSetで「DataSet.Tables.Add(DataTabel)」した後のDataTableは、Disposeしても
DataSetに影響はないでしょうか?
DataGridで「DataGrid.SetDataBinding(DataSet, DataSet.Tables[0].TableName)」
した後のDataSetは、DisposeしてもDataGridに影響はないでしょうか?
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-07-07 16:13
引用:

梶さんの書き込み (2006-07-07 13:38) より:

現在は、各メソッド・イベント内で解放忘れのリソースが無いか調査しており、
メソッドのローカルに作成したDataSetやDataTableがDisposeされていない場所が、何箇所か見つかりました。
取り敢えずは、これらにDispose+nullセットを施そうと考えています


そういうことでしたか。
考えられている対策を施せば、多分問題ないと思います。
(ローカルですから、Dispose だけでも良いと思います)

引用:

ちなみに・・・
DataSetで「DataSet.Tables.Add(DataTabel)」した後のDataTableは、Disposeしても
DataSetに影響はないでしょうか?
DataGridで「DataGrid.SetDataBinding(DataSet, DataSet.Tables[0].TableName)」
した後のDataSetは、DisposeしてもDataGridに影響はないでしょうか?


是非、'実際に' お試しになって、インスタンスについての理解を深めてください。
先ほどの繰り返しになってしまうかもしれませんが、実証することが大事だと思います。
(それは自分の中に刻まれやすいものです)

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌

スキルアップ/キャリアアップ(JOB@IT)