为什么Timer只执行一次?

时间:2018-02-09 17:46:25

标签: c# timer

我写这段代码:

 Timer timer = new Timer(Callback, "", TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(20));

但只执行一次回调方法。我需要每20秒执行一次回调方法。

2 个答案:

答案 0 :(得分:0)

演示垃圾收集对“超出范围”计时器的影响,不再被任何实例记住:

static void Main(string[] args)
{
    System.Threading.Timer timer = new System.Threading.Timer(o => { Console.WriteLine(DateTime.Now); }, "", TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2));

    if (true)
    {
        // declared here and soon out of scope but works until garbage collected.
        new System.Threading.Timer(o => { Console.WriteLine($"Inner {DateTime.Now}"); }, "", TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2));
    }

    Console.ReadLine();  //  wait 5-6 printouts, hit return once

    // force garbage collection. This happens from time to time by itself when your
    // ressources gets scarce and C# runtime "thinks" it is time to GC. 
    GC.Collect();
    GC.WaitForPendingFinalizers();

    Console.ReadLine();  //  wait some more .. only 1 timer prints anymore
}

输出:

09.02.2018 18:57:27
Inner 09.02.2018 18:57:27
09.02.2018 18:57:29
Inner 09.02.2018 18:57:29
09.02.2018 18:57:31
Inner 09.02.2018 18:57:31      // hit retun once

09.02.2018 18:57:33
09.02.2018 18:57:35
09.02.2018 18:57:37
09.02.2018 18:57:39

您可以通过声明您的计时器不是本地但是作为类实例的成员来避免GC,GC只会“删除”不再引用的内容(简化说明)。只要你有这个类的“实时”实例,一个类的成员就会保持“滴答作响”。

查看/阅读garbage-collection

  

只要托管堆中的地址空间可用,运行时就会继续为新对象分配空间。但是,记忆并不是无限的。最终垃圾收集器必须执行一个集合才能释放一些内存。垃圾收集器的优化引擎根据正在进行的分配确定执行收集的最佳时间。

答案 1 :(得分:0)

假设你正在使用System.Threading.Timer它应该工作,如果(正如其他人所说)计时器不会超出范围并被处置/ GC' d。这是一个控制台应用程序,显示它正在运行:

class Program
{
    class TimerTest
    {
        private Timer timer1;

        private void Callback1(object state)
        {
            Console.WriteLine("Callback1");
        }
        private void Callback2(object state)
        {
            Console.WriteLine("Callback2");
        }

        public TimerTest()
        {
            // Class scoped timer
            timer1 = new Timer(Callback1, "", TimeSpan.FromSeconds(0.1), TimeSpan.FromSeconds(0.20));

            // Function scoped Timer (force displose with using)
            using (Timer timer2 = new Timer(Callback2, "", TimeSpan.FromSeconds(0.1), TimeSpan.FromSeconds(0.20)))
            {
                // Give some time for timer2 callbacks
                Thread.Sleep(500);
            }
        }
    }


    static void Main(string[] args)
    {
        TimerTest test = new TimerTest();

        while (true) Thread.Sleep(1000);
    }
}

结果如下:

Callback2
Callback1
Callback2
Callback1
Callback1
Callback1
Callback1
Callback1
Callback1
Callback1
Callback1
Callback1
Callback1
Callback1
Callback1
...