DOBON.NET DOBON.NETプログラミング掲示板過去ログ

Showで開いたFormへの参照が消えるタイミングを教えてください

環境/言語:[.Net Framework2.0]
分類:[.NET]

FormのShowメソッドで表示したフォームを、×ボタンで閉じても、
インスタンスが残っているようです。Showで開いたフォームは、×
ボタンで無くなるとおもっていたのですが、これはなぜでしょうか?

試したソースは以下となります。
Form1にボタンを二つ(button1とbutton2)を配置し、button1から
からForm2をShowで表示します。Form2を表示する際、Form2側にForm1
のbutton1クリックのイベントを監視できるようにしています。

Form2では、Form1で発生したイベントに対し、メッセージボックスを
表示します。また、Disposedイベントにハンドラをつけて、ここでも
メッセージ表示するようにしています。

ここで、Form1からbutton1をクリックしてForm2のインスタンスを1つ
作成してShowにて表示して、すぐにForm2のウィンドウを閉じます。
閉じると、Disposedイベントが発生して、「Disposed!」と表示されま
す。

ここでForm1のbutton2をクリックすると、閉じたはずで、Disposedイベ
ントも発生したForm2のイベントハンドラが働いたようで、「ある!」
とメッセージ表示されます。

DisposeされたはずのForm2から、メッセージが出てきてしまう理由が
いまいちわかりません。単純に、イベントハンドラの形でForm1への
参照が残っていたからなのでしょうか?


○Program.cs
static class Program
{
/// <summary>
/// アプリケーションのメイン エントリ ポイントです。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}

○Form1 ボタンを2つ配置する。
public partial class Form1 : Form
{
// イベント
public event EventHandler<EventArgs> ClickEvent = delegate { };

public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
Form2 frm = new Form2();
frm.SetEvent(this);
frm.Show();
}

private void button2_Click(object sender, EventArgs e)
{
this.ClickEvent(this, new EventArgs());
}
}

○Form2
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
this.Disposed += new EventHandler(Form2_Disposed);
}

void Form2_Disposed(object sender, EventArgs e)
{
MessageBox.Show("Disposed!");
}

public void SetEvent(Form1 frm)
{
frm.ClickEvent += new EventHandler<EventArgs>(frm_ClickEvent);
}

void frm_ClickEvent(object sender, EventArgs e)
{
MessageBox.Show("ある!");
}
}
■No29898に返信(なおじさんの記事)
> FormのShowメソッドで表示したフォームを、×ボタンで閉じても、
> インスタンスが残っているようです。Showで開いたフォームは、×
> ボタンで無くなるとおもっていたのですが、これはなぜでしょうか?

まずはじめに、Dispose と参照がなくなること自体に直接関係はありません。
Dispose されようと参照が残ることがありますし、参照がなくなったとしても Dispose されないことがあります。
Dispose がどういう位置づけのメソッドか一度調べてみてください。


> DisposeされたはずのForm2から、メッセージが出てきてしまう理由が
> いまいちわかりません。単純に、イベントハンドラの形でForm1への
> 参照が残っていたからなのでしょうか?

先にも書きましたが、Dispose と参照は関係ありません。
なので、Dispose しようと参照が残っているのでイベントハンドラは呼び出されます。
こういうことを起こしたくないのであれば、Dispose の時にイベントハンドラを -= で外してください。

なお、イベントハンドラのインスタンス(デリゲート)には、そのイベントを持つオブジェクトへの参照とメソッドの情報が含まれています。
今回の例でいくと、Form2 のメソッドを Form1 のイベントに登録していた場合、Form1 が参照されなくなるか、Form1 のイベントからあなたが明示的に外さない限り、Form2 の参照は残り続けます。
Azuleanさん、早速ご返信頂ありがとうございます。
> まずはじめに、Dispose と参照がなくなること自体に直接関係はありません。
ということで、すみません、理解が足らなかったようです。
> こういうことを起こしたくないのであれば、Dispose の時にイベントハンドラを -= で外してください。
のようにするようにします。
ありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板