【问题标题】:Timer only works in debug mode定时器仅在调试模式下工作
【发布时间】:2014-08-28 10:39:11
【问题描述】:

我有一个带有以下主程序的控制台应用程序:

    static void Main(string[] args)
    {
        var timer = new System.Threading.Timer(
         e =>
            {
            //some code here
        },
        null,
        TimeSpan.Zero,
        TimeSpan.FromMinutes(1));


        var backupTimer = new System.Threading.Timer(
         e =>
         {
             //some code here

         },
        null,
        TimeSpan.Zero,
        TimeSpan.FromHours(24));

        Console.ReadLine();

    }

问题在于,在调试模式下它工作正常,并在正确的时间段内调用两个计时器中的方法,如果在控制台中输入某些内容,程序将结束工作(Console.ReadLine() 就是为了那个),但是当我运行程序时在 Release 模式下,两个定时器只调用一次(第一次),然后程序只是等到我输入一些东西。

如何解决这个问题,以便我可以编译一个正常工作的独立程序?

【问题讨论】:

  • 看起来定时器被 GC 抑制了。
  • 您需要保留对计时器的引用作为字段。否则,GC 会吃掉它。
  • 那为什么在调试模式下能正常工作呢?
  • 参考herehere
  • @AdrianoRepetti 不,JIT 很聪明,可以判断是否不再使用本地人。如果没有,jit 会告诉 GC 他们可以被 GC'd。请参考我上面的评论,汉斯解释得很好..

标签: c# debugging timer release


【解决方案1】:

正如@SriramSakthivel 建议的那样,您必须将对计时器的引用保留为一个字段,否则垃圾收集器会吃掉您的计时器。 所以这里是解决方案:

    private static System.Threading.Timer timer;
    private static System.Threading.Timer backupTimer;

    static void Main(string[] args)
    {

        timer = new System.Threading.Timer(
         e =>
            {
            //something
        },
        null,
        TimeSpan.Zero,
        TimeSpan.FromMinutes(1));


        backupTimer = new System.Threading.Timer(
         e =>
         {
             //something

         },
        null,
        TimeSpan.Zero,
        TimeSpan.FromHours(24));

        Console.ReadLine();

    }

【讨论】:

    【解决方案2】:

    希望以下解决方案有所帮助!

    问题:

    通过显示当前时钟时间,以下代码始终按预期工作。

     class Program
     {
            static void TimerProcedure(object param)
            {
                Console.Clear();
                Console.WriteLine(DateTime.Now.TimeOfDay);
    
                GC.Collect();
    
            }
    
            static void Main(string[] args)
            {
                Console.Title = "Desktop Clock";
                Console.SetWindowSize(20, 2);
                Timer timer = new Timer(TimerProcedure, null,
                    TimeSpan.Zero, TimeSpan.FromSeconds(1));
                Console.ReadLine();
            }
        }
    

    但是,如果您在发布模式下运行相同的代码,它只会在第一次显示当前时间,但之后不会更新。

    解决方案

    通过添加 GC.KeepAlive(object) 的简单调整将使其在发布模式下也可以正常工作。参考下面的代码。

    class Program
        {
            static void TimerProcedure(object param)
            {
                Console.Clear();
                Console.WriteLine(DateTime.Now.TimeOfDay);
                #region Hidden
                GC.Collect();
                #endregion
            }
    
            static void Main(string[] args)
            {
                Console.Title = "Desktop Clock";
                Console.SetWindowSize(20, 2);
                Timer timer = new Timer(TimerProcedure, null,
                    TimeSpan.Zero, TimeSpan.FromSeconds(1));
                Console.ReadLine();
                GC.KeepAlive(timer);
            }
        }
    

    替代解决方案:正在使计时器成为类级别的静态变量

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多