@IT会議室は、ITエンジニアに特化した質問・回答コミュニティ「QA@IT」に生まれ変わりました。ぜひご利用ください。
- PR -

【C#】モードレス画面のGC管理について

1
投稿者投稿内容
Makoto
大ベテラン
会議室デビュー日: 2004/03/31
投稿数: 133
投稿日時: 2006-02-27 09:39
いつもお世話になっております。

下記のようなコードを書いた場合に関して質問です。
 @の場合には、ShowDialog()の応答を待ちますので、ListdlgはGCの対象にはならない。
 Aの場合には、Show()で応答を待たないので、参照は0になる?(=あるとき突然なくなっている?)。

このような場合にはAの画面Listdlgは、表示した状態で放置して置くとGCにより削除されてしまうのでしょうか?

ちなみに、Aを使用する場合には、
画面オブジェクトをローカル変数としてではなく上位オブジェクトのメンバコンテナに保持し、
Dispose()処理をselectFormクラスのClosedイベント内に
実装しようかと思うのですが、これって安全なのでしょうか?
(『自分で自分を削除すること(=delete this みたいな扱い)』になりますか?)

現在Outlookアドインを開発中で、画面のボタン操作からOutlookのアドレス帳編集画面を開く必要があります。
単純に@案を使用したかったのですが、Outlookのアドレス帳編集画面を開くにはモーダル画面表示中には実行できないようなのです。

そこで、A案で行う必要があるのですが、画面の削除タイミングなどが気になっています。
ご存知の方いらっしゃいましたら、アドバイスをお願いいたします。

@モーダル画面表示の例
void ShowModal()
{
selectForm Listdlg = new selectForm();
Listdlg.ShowDialog();
Listdlg.Hide();
Listdlg.Dispose();
Listdlg=null;
}

Aモードレス画面表示の例
void ShowUnModal()
{
//画面上に設定する。※モーダルでない場合には、画面がローカル変数になる。GCの対象になるのか?
selectForm Listdlg = new selectForm();
Listdlg.Show();
}

※selectFormは、formクラスの派生クラスです。

以上、よろしくお願いいたします。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-27 10:34
引用:

Makotoさんの書き込み (2006-02-27 09:39) より:

このような場合には (2) の画面Listdlgは、表示した状態で放置して置くとGCにより削除されてしまうのでしょうか?


されません。

Close メソッド (Dispose メソッド) が呼び出されない限りは、
GC は必要なものと判断し、回収されることはありません。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
Makoto
大ベテラン
会議室デビュー日: 2004/03/31
投稿数: 133
投稿日時: 2006-02-27 10:57
回答ありがとうございます。

下記のような認識で、大丈夫そうですね。

@モーダル画面では、
 ユーザ操作により画面入力完了後に、
 Closeメソッドをコールする(=自動的にDisposeされる)

Aモードレス画面では、
 ユーザ操作により画面入力完了(OK、閉じるなどクリック)後に、
 メソッド内でCloseメソッドをコールすると自動的にDisposeされる。

あるいは、@、A共に、Closedイベントを作成し、内部でDisposeする
ように明示的に記述する必要がある。

ちなみに、ここで聞く内容ではないですが、
Javaの場合もやはり同様なのでしょうか?
C#にしろJavaにしろ、メモリをマネージされている場合には、
GC周りの処理で削除対象になっているのかがはっきりしないので、
『(念のため)確実に参照しているように、自AP内で参照しておく』
ようにしていたりという声を聞いたもので...

GCの振る舞いがよくわからないだけなのですが...
(ドキュメントの読みが足りないだけ?)

もし参照しているつもり、参照されていないつもりの場合に、
それぞれ突如メモリアクセス違反や
メモリリーク(リソースリーク)が発生してくると、
(ここは無関係と思い込んでしまい、)原因の特定は
難しいだろうなぁと思ったもので...
(愚痴ってしまい、すみません...)

回答ありがとうございました。
自信を持ってローカル変数でモードレスFormを作成します。

以上、お忙しいとは思いますが、よろしくお願いいたします。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-02-27 11:29
引用:

Makotoさんの書き込み (2006-02-27 10:57) より:

(1)モーダル画面では、
 ユーザ操作により画面入力完了後に、
 Closeメソッドをコールする(=自動的にDisposeされる)


うーん、ShowDialog メソッドの場合は呼び出し側で Dispose してあげてください。
Close 以外でも制御が帰ってくることはあるわけで、Dispose を保証しておく必要があります。

引用:

(2)モードレス画面では、
 ユーザ操作により画面入力完了(OK、閉じるなどクリック)後に、
 メソッド内でCloseメソッドをコールすると自動的にDisposeされる。


モードレスは、まあこれで良いでしょう。

  フォームのDisposeについて

引用:

あるいは、(1)、(2)共に、Closedイベントを作成し、内部でDisposeする
ように明示的に記述する必要がある。


これは必要はないです。
むしろ、ObjectDisposedException などが発生する恐れもあります。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
Makoto
大ベテラン
会議室デビュー日: 2004/03/31
投稿数: 133
投稿日時: 2006-02-27 11:53
回答ありがとうございます。

Dispose()の件、了解しました。
自信を持ってモードレスFormをローカルで作成してみます。
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2006-02-27 13:14
どうやって実現されているのか気になって調べてみました。(今まで気にもとめていなかったとは…>自分)

Form だけ特別扱いしているのか?
いやそんなはずはない。そんな事をしたら GC の実装が複雑になる。特別扱いしなければならない項目毎に GC が複雑化する。

もしかして隠しフォームが存在して、いかなるフォームもそれの子フォームになっている?トップレベルウィンドウはデスクトップの子だから、CLR はデスクトップを表現するコントロールを持っている?
トップレベルフォームの Parent は常に null だ。だから違う。

NativeWindow クラスの説明に以下の文言発見。
「ウィンドウは、ウィンドウ ハンドルが関連付けられている場合は、ガベージ コレクションの対象にはなりません。」
そうか。有効なウィンドウハンドルを特別視しているようだ。NativeWindow のインスタンスは System.Windows.Forms.Control 内にある。つまり Form も同じだ。

どのように特別視しているのか?
NativeWindow の中に、GCHandle のインスタンスがある。

つまり、この GCHandle クラスがガベージコレクションの対象にするかどうかを制御しているわけですね。
GCHandle がトップレベルフォームを循環で参照し、ガベージコレクションの対象になる事を防いでいるようです。

_________________
囚人のジレンマな日々
1

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