详解C#中的定时器Timer类及其垃圾回收机制

2019-12-30 12:12:32王旭

release模式编译生成的IL:


.method private hidebysig static void Main(string[] args) cil managed
{
 .entrypoint
 // Code size    32 (0x20)
 .maxstack 8
 IL_0000: ldnull
 IL_0001: ldftn   void GCTest.Program::TimerCallback(object)
 IL_0007: newobj   instance void [mscorlib]System.Threading.TimerCallback::.ctor(object,
                                           native int)
 IL_000c: ldnull
 IL_000d: ldc.i4.0
 IL_000e: ldc.i4   0x7d0
 IL_0013: newobj   instance void [mscorlib]System.Threading.Timer::.ctor(class [mscorlib]System.Threading.TimerCallback,
                                       object,
                                       int32,
                                       int32)
 IL_0018: pop
 IL_0019: call    string [mscorlib]System.Console::ReadLine()
 IL_001e: pop
 IL_001f: ret
} // end of method Program::Main

debug模式下生成的IL:


method private hidebysig static void Main(string[] args) cil managed
{
 .entrypoint
 // Code size    33 (0x21)
 .maxstack 4
 .locals init ([0] class [mscorlib]System.Threading.Timer timer)
 IL_0000: nop
 IL_0001: ldnull
 IL_0002: ldftn   void GCTest.Program::TimerCallback(object)
 IL_0008: newobj   instance void [mscorlib]System.Threading.TimerCallback::.ctor(object,
                                           native int)
 IL_000d: ldnull
 IL_000e: ldc.i4.0
 IL_000f: ldc.i4   0x7d0
 IL_0014: newobj   instance void [mscorlib]System.Threading.Timer::.ctor(class [mscorlib]System.Threading.TimerCallback,
                                       object,
                                       int32,
                                       int32)
 IL_0019: stloc.0
 IL_001a: call    string [mscorlib]System.Console::ReadLine()
 IL_001f: pop
 IL_0020: ret
} // end of method Program::Main

从生成的IL中我们可以看出在debug模式下,生成IL比在release模式下多了19行红色字体的IL指令码,该指令码的作用是将15行生成的引用Timer对象的栈上的变量存放到局部变量0中。所以使得在debug模式下该t还被引用,不能够回收Timer对象,所以也能出现我们期盼的结果,那么如何在两种模式下都能得到我们期盼的结果呢。我们可以如下操作。

正确的代码:


class Program
  {
    static void Main(string[] args)
    {
      Timer timer = new Timer(TimerCallback,null,0,2000);
    
      Console.ReadLine();
      timer.Dispose();
    }

    private static void TimerCallback(object o)
    {
      Console.WriteLine("in TimerCallback method");

      GC.Collect();

      
    }
  }

这时不管是在release模式下还是debug模式下,都会每隔2秒钟调用我们的回调方法。



注:相关教程知识阅读请移步到c#教程频道。