2

Ok、

そのため、Silverlight アプリケーションで誰かがアイコンをクリックすると起動するメソッドがあります。以下を参照してください。

    private void Logo_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        e.Handled = true;
        ShowInfo(true);

        DispatcherTimer autoCloseTimer = new DispatcherTimer();
        autoCloseTimer.Interval = new TimeSpan(0, 0, 10);
        autoCloseTimer.Tick +=new EventHandler((timerSender,args) => 
            {
                autoCloseTimer.Stop();
                ShowInfo(false);
            });
        autoCloseTimer.Start();
    }

メソッド ShowInfo() が会社情報を含むボックスを開き、ディスパッチ タイマーが上記のタイムスパンの後にボックスを自動的に閉じることを意味します。そして、これはすべて機能します...

しかし、わからないのは、ディスパッチ タイマーがローカル変数であるため、Logo_MouseLeftButtonUp メソッドが終了した後、匿名メソッドが起動される前に、ディスパッチ タイマーを参照して GC コレクションに使用できないようにするために何があるのでしょうか?

匿名メソッドの ShowInfo() メソッドへの参照ですか?

イベントなどを使用して想像できるように、このようなものでリークを作成するのは非常に簡単です。

これがすべて理にかなっていることを願っています!

アンディ。

4

2 に答える 2

10

Dispatcher.AddTimerDispatcherTimer は、 を呼び出すときに内部メソッドを呼び出すことで、自分自身を Dispatcher に登録しますStart

Dispatcher.RemoveTimerを呼び出すと、それ自体も登録解除されるためStop、メモリ リークは発生しません。

は、そのイベントTimerで匿名メソッドを存続させTickます。これにより、メソッド内の変数もクロージャーを通じて存続します。

于 2010-06-02T14:07:09.420 に答える
1

.NET でメモリ リークが発生する原因として、あまり知られていないものの 1 つは、イベント ハンドラーです。イベント ハンドラーはオブジェクトへの参照であり、オブジェクトをスコープ内に保持します。イベント ハンドラーを使い終わったら、それを削除する必要があります。イベント ハンドラーが 1 回しか使用されない場合は、それ自体を登録解除できますが、2 回以上使用される場合は、イベント ハンドラーが不要になったことを認識し、イベント ハンドラーを削除する別のオブジェクトが必要になります。

于 2010-06-02T14:12:32.747 に答える