定时器仅在调试模式下工作
Posted
技术标签:
【中文标题】定时器仅在调试模式下工作【英文标题】: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 会吃掉它。 那为什么在调试模式下能正常工作呢? 参考here和here @AdrianoRepetti 不,JIT 很聪明,可以判断是否不再使用本地人。如果没有,jit 会告诉 GC 他们可以被 GC'd。请参考我上面的评论,汉斯解释得很好.. 【参考方案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);
替代解决方案:正在使计时器成为类级别的静态变量
【讨论】:
以上是关于定时器仅在调试模式下工作的主要内容,如果未能解决你的问题,请参考以下文章
OpenGL 程序仅在 Visual Studio 2013 中的调试模式下工作
父 NSManagedObjectContext 在子保存后没有变化,但仅在发布模式下(在调试模式下工作)