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 线程上执行,因此事件处理方法可能在一个线程上运行,同时对 Stop 方法的调用在另一个线程上运行。这可能会导致在调用 Stop 方法后引发 Elapsed 事件。下一节中的代码示例显示了一种解决这种竞争条件的方法。

MSDN:Timer.Stop 方法

于 2012-10-28T03:54:19.700 回答