void Foo()
{
System.Windows.Forms.Form f = new System.Windows.Forms.Form();
f.Show();
}
私の理解では、fはフォームへの参照を保持しています。ただし、fはローカル変数であり、コントロールが中括弧を離れるとスコープ外になります。しかし、フォームはまだ開いています。GC.Collect()を呼び出してみましたが、フォームはまだ開いています。
もう1つのシナリオ。
private void button2_Click(object sender, EventArgs e)
{
Timer t = new Timer();
t.Enabled = true;
t.Interval = 1000;
t.Tick += new EventHandler(t_Tick);
}
void t_Tick(object sender, EventArgs e)
{
}
このシナリオでは、tがガベージコレクションを取得することはありません。多くの調査の結果、t.Enabled = trueに設定すると、Timerクラスが-GCHandle.Allocを使用して収集しないようにGCに要求していることがわかりました。皆さん、これはメモリリークの大きな原因です。t.Enabled = falseに設定しない限り、フォームを閉じた後でもフォーム全体がリークされます。
最初のサンプルコードでは、GC.Collect()をトリガーした後でも、フォームがガベージコレクションを取得しなかった理由を理解できませんでした。リフレクターでは、ControlNativeWindowがGCHandle.Allocを内部的に使用するFormで使用されているのを見ました。それが理由ですか?.NETライブラリのユーザーとして、私は常に、参照に到達できなくなると、ガベージコレクションの機会が得られると信じていました。もちろん、ガベージコレクションとメモリからの実際の解放は決定論的ではありません。しかし、ここでの私の質問は-両方の例について私の理解は正しいですか?到達不能になった後も存続できるオブジェクトがある場合、メモリリークを防ぐためにそれをどのように追跡しますか?