14


4

タイマー、イベント、ガベージコレクション:何か不足していますか?

次のコードを見てください。

class TestTimerGC : Form
{
    public TestTimerGC()
    {
        Button btnGC = new Button();
        btnGC.Text = "GC";
        btnGC.Click += (sender, e) => GC.Collect();
        this.Controls.Add(btnGC);

        System.Windows.Forms.Timer tmr = new System.Windows.Forms.Timer();
        tmr.Interval = 1000;
        tmr.Tick += (sender, e) => this.Text = DateTime.Now.ToString();
        tmr.Start();
    }
}

誤解しない限り、 tmr`変数がスコープ外に出た後、 Timer`はどこからも参照されないため、ガベージコレクションの対象になります。 しかし、GCボタンをクリックすると、タイマーの実行が継続されるため、収集されなかったと思います…​

誰にもその説明がありますか?

PS:もちろん実際のプログラムではありません。誰かにポイントを証明しようとしていました…​ しかし、私の証明は機能しませんでした;)

1 Answer


20


OK、私は何が起こっているのか知っていると思う…​ Reflectorで Timer`クラスのコードを見て、 Enabled`プロパティのセッターで次の命令を見つけました:

this.timerRoot = GCHandle.Alloc(this);

そのため、開始されると、タイマーはそれ自体に `GCHandle`を割り当て、GCによる収集を防ぎます…​