2

System.Timers.Timerに続いて、演習用のコンソール アプリを作成しました。

public class Program
{
    //private static System.Timers.Timer aTimer;

    public static void Main()
    {
        short_running_method();

        Console.WriteLine("Press the Enter key to exit the program.");
        Console.ReadLine();


    }

    static void short_running_method()
    {
        // Normally, the timer is declared at the class level, 
        // so that it stays in scope as long as it is needed. 
        // If the timer is declared in a long-running method,   
        // KeepAlive must be used to prevent the JIT compiler  
        // from allowing aggressive garbage collection to occur  
        // before the method ends. You can experiment with this 
        // by commenting out the class-level declaration and  
        // uncommenting the declaration below; then uncomment 
        // the GC.KeepAlive(aTimer) at the end of the method. 
        System.Timers.Timer aTimer; 

        // Create a timer with a ten second interval.
        aTimer = new System.Timers.Timer(10000);

        // Hook up the Elapsed event for the timer.
        aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);

        // Set the Interval to 2 seconds (2000 milliseconds).
        aTimer.Interval = 2000;
        aTimer.Enabled = true;

        // If the timer is declared in a long-running method, use 
        // KeepAlive to prevent garbage collection from occurring 
        // before the method ends. 
        //GC.KeepAlive(aTimer);
    }


    // Specify what you want to happen when the Elapsed event is  
    // raised. 
    private static void OnTimedEvent(object source, ElapsedEventArgs e)
    {
        Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
    }
}

プログラムが実行され、イベントが無限に発生し続ける限り、クラスレベルで宣言されたタイマーオブジェクトが生きていることを理解しています(間違っていたら訂正してください)。クラス レベルで宣言されたタイマー オブジェクトをコメント アウトし、short_running_method 内の宣言のコメントを解除することで、GC.KeepAlive(aTimer) が使用されず、イベントの発生が停止する場合、atimer オブジェクトは一定時間後にガベージ コレクションされるはずです。ただし、私の実験では、30 分後でもイベントが発生しているように見えます。誰かがなぜこれが起こっているのかを明確にすることができますか?

4

1 に答える 1

0

問題は、イベント ソースからイベント リスナーへの強い参照にあります。

aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);

したがって、ここで 弱いイベント パターンを探しているかもしれません: MSDN の弱いイベント パターン

また、タイマーを停止するには、次を使用できます。

aTimer.Stop();

Enabledを falseに設定して、タイミングを停止することもできます。

Elapsed イベントを発生させるシグナルは、常に ThreadPool スレッドでの実行のためにキューに入れられるため、イベント処理メソッドが 1 つのスレッドで実行されると同時に、Stop メソッドの呼び出しが別のスレッドで実行される可能性があります。これにより、Stop メソッドが呼び出された後に Elapsed イベントが発生する可能性があります。次のセクションのコード例は、この競合状態を回避する 1 つの方法を示しています。

MSDN: Timer.Stop メソッド

于 2012-10-28T03:54:19.700 に答える