【问题标题】:Systems.Timers.Timer works in debug, but not releaseSystems.Timers.Timer 在调试中工作,但不是发布
【发布时间】:2016-05-16 18:54:39
【问题描述】:
System.Timers.Timer timer= new System.Timers.Timer(1);
            timer.AutoReset = true;
            timer.Elapsed += (s, e) =>
            {
                Console.WriteLine("fired");
            };
timer.Start();

该事件始终在调试模式下触发,而在发布模式下始终不触发。我尝试禁用编译器优化,但没有帮助。

我正在尝试在 asp.net mvc 应用程序 .net 4.6 框架中运行它

【问题讨论】:

  • Console.WriteLine 是否可能无法在发布模式下工作?我之所以问是因为我遇到了 Console.WriteLine 在一种配置中记录到 VS 输出窗口但在另一种配置中没有(从未弄清楚原因)的问题。在你责怪计时器之前可能值得检查一下。
  • 您确定甚至运行代码块以在释放模式下启动计时器吗?另外,您将问题标记为 asp.net,也许您的应用程序域正在关闭?
  • 如何确定我的计时器正在运行?我知道它是以正确的间隔创建的。另外,我不确定这是否与asp有关,但我认为额外的信息不会受到伤害。我的应用程序域在发布时被关闭但在调试中没有被关闭是否有意义?
  • 您是否在代码中使用了编译器指令?
  • 不确定你的意思,但我尝试添加注释以防止编译时优化,但没有帮助

标签: c# asp.net-mvc timer


【解决方案1】:

您的计时器可能没问题,但您的测试方法有缺陷。

在 ASP.NET 应用程序中以发布模式写入 Console.WriteLine 的数据丢失。看这个问题的答案:Where does Console.WriteLine go in ASP.net production environment?

如果你真的想使用 Console.WriteLine,你可以使用Console.SetOut 将输出重定向到一个文件。

另外,请确保您的 timer 对象没有在方法中声明,因为它会在方法完成后立即销毁。

【讨论】:

  • 我尝试了不同的方法,包括抛出异常......在发布版本中没有发生任何事情,并且调试仍然可以正常工作
  • 定时器的 Elapsed 事件在不同的线程中运行。没有什么可以捕获异常,所以线程只会死,而不是整个应用程序。未处理的异常可能显示在 Windows 应用程序事件日志中。
  • 我在应用程序启动时有这个,所以应用程序应该抛出一个异常,这在调试模式下会发生,但在发布时不会发生
  • 更多上下文也可能有所帮助。所有这些代码都在一种方法中吗?您的 timer 对象需要处于能够存活足够长以触发的上下文中。
  • 我的计时器是一个类变量,只要他的应用程序正在运行,这个类就有生命周期
【解决方案2】:

您的计时器设置为 1 毫秒。这可能会产生一些不可预测的结果,因为“分辨率”(检查计时器的时间间隔)通常约为 15 毫秒。如果您只是想测试计时器的行为,那么我会将其增加到 20 毫秒或更多。

我对此进行了测试。运行 500 毫秒的 1 毫秒间隔持续经过 32 次 - 大约每 15 毫秒一次。这在调试和发布中是一样的。没有抛出异常。

我建议在计时器结束时将项目添加到全局可访问的ConcurrentQueue,而不是写入控制台(因为这仅用于测试/实验。)

然后在网页上您可以输出队列的内容。您可能想先停止计时器,这样它就不会一直将项目泵入队列。 (或者只是使用更长的间隔。)

【讨论】:

    【解决方案3】:

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

    问题:

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

     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);
            }
        }
    

    针对您的具体问题,验证 timer 变量的范围是否是方法的本地变量。如果这是真的,你可以让它保持活力,如上所示。

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

    【讨论】:

      猜你喜欢
      • 2020-09-16
      • 1970-01-01
      • 2012-04-07
      • 2020-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多