c# timer 销毁_你需要知道的c# Timer 的垃圾回收机制。

通常我们需要定时执行一段任务的时候,我们就需要定时器,这时我们就可以使用c# System.Threading空间中的 Timer定时器;他是个异步定时器,时间到时每次都是在线程池中分配一个线程去执行任务。下面我们来看一个有趣的例子:

class Program

{

static void Main(string[] args)

{

Timer timer = new Timer(TimerCallback,null,0,2000);

Console.ReadLine();

}

private static void TimerCallback(object o)

{

Console.WriteLine("in TimerCallback method");

GC.Collect();

}

}

当我们在debug模式下运行该段程序时,正如我们期盼的那样程序会每隔2秒钟执行该方法,打印出"in TimerCallback method”,而在release模式下执行的时候,只执行一次该方法,字符串只打印一次。在这里我们在调用TimerCallback方法时,强制执行垃圾回收器,说明在release模式下,垃圾回收器执行回收算法时,首先假设所有对象都是可回收的,当将Timer对象赋值给变量t后,t没有在被引用,因此也就没有变量引用Timer对象,所以垃圾收集这时会回收Timer对象。那么为什么在debug模式下却能够运行能,这跟c#编译器的优化方式有关,在release模式下编译器做了相关的优化操作。而在debug模式下,timer对象的生成期是方法的结束,这样做也是为了调试的方便。要不然在调试时,我们执行到Timer timer = new Timer()后想看timer的值时,已经被垃圾回收器给回收了,这是我们不期望看到的结果,编译器如何处理的,我们可以看看编译器在release模式下和debug模式下对上面的代码编译后生成的IL对比我们既知结果。

release模式编译生成的IL:

1 .method private hidebysig static void Main(string[] args) cil managed2 {3 .entrypoint4 //Code size 32 (0x20)

5 .maxstack 8

6 IL_0000: ldnull7 IL_0001: ldftn void GCTest.Program::TimerCallback(object)8 IL_0007: newobj instance void [mscorlib]System.Threading.TimerCallback::.ctor(object,9 native int)10 IL_000c: ldnull11 IL_000d: ldc.i4.0

12 IL_000e: ldc.i4 0x7d0

13 IL_0013: newobj instance void [mscorlib]System.Threading.Timer::.ctor(class[mscorlib]System.Threading.TimerCallback,14 object,15 int32,16 int32)17 IL_0018: pop18 IL_0019: call string[mscorlib]System.Console::ReadLine()19 IL_001e: pop20 IL_001f: ret21 } //end of method Program::Main

debug模式下生成的IL:

1 method private hidebysig static void Main(string[] args) cil managed2 {3 .entrypoint4 //Code size 33 (0x21)

5 .maxstack 4

6 .locals init ([0] class[mscorlib]System.Threading.Timer timer)7 IL_0000: nop8 IL_0001: ldnull9 IL_0002: ldftn void GCTest.Program::TimerCallback(object)10 IL_0008: newobj instance void [mscorlib]System.Threading.TimerCallback::.ctor(object,11 native int)12 IL_000d: ldnull13 IL_000e: ldc.i4.0

14 IL_000f: ldc.i4 0x7d0

15 IL_0014: newobj instance void [mscorlib]System.Threading.Timer::.ctor(class[mscorlib]System.Threading.TimerCallback,16 object,17 int32,18 int32)19 IL_0019: stloc.0

20 IL_001a: call string[mscorlib]System.Console::ReadLine()21 IL_001f: pop22 IL_0020: ret23 } //end of method Program::Main

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

正确的代码:

1 classProgram2 {3 static void Main(string[] args)4 {5 Timer timer = new Timer(TimerCallback,null,0,2000);6

7 Console.ReadLine();8 timer.Dispose();9 }10

11 private static void TimerCallback(objecto)12 {13 Console.WriteLine("in TimerCallback method");14

15 GC.Collect();16

17

18 }19 }

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值