你需要知道的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:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 32 (0x20)
.maxstack
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.
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
.locals init ([] 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.
IL_000f: ldc.i4 0x7d0
IL_0014: newobj instance void [mscorlib]System.Threading.Timer::.ctor(class [mscorlib]System.Threading.TimerCallback,
object,
int32,
int32)
19 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,,); Console.ReadLine();
timer.Dispose();
} private static void TimerCallback(object o)
{
Console.WriteLine("in TimerCallback method"); GC.Collect(); }
}
这时不管是在release模式下还是debug模式下,都会每隔2秒钟调用我们的回调方法。
你需要知道的c# Timer 的垃圾回收机制。的更多相关文章
- Java_垃圾回收机制(未掌握)
垃圾回收机制 任何一种垃圾回收算法一般要做两件基本事情: 发现无用的对象(没有任何变量引用该对象) 回收无用对象占用的内存空间 垃圾回收相关算法: 引用计数法, 引用可达法 分代垃圾回收机制: 不同的 ...
- 垃圾回收机制GC知识再总结兼谈如何用好GC
一.为什么需要GC 应用程序对资源操作,通常简单分为以下几个步骤: 1.为对应的资源分配内存 2.初始化内存 3.使用资源 4.清理资源 5.释放内存 应用程序对资源(内存使用)管理的方式,常见的一般 ...
- JAVA的垃圾回收机制
1. 垃圾回收的意义 在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象:而在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾.JVM的 ...
- 转!!Java垃圾回收机制
1. 垃圾回收的意义 在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象:而在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾.JVM的 ...
- java基础之 垃圾回收机制
1. 垃圾回收的意义 在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象:而在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾.JVM的 ...
- 垃圾回收机制GC知识再总结兼谈如何用好GC(转)
作者:Jeff Wong 出处:http://jeffwongishandsome.cnblogs.com/ 本文版权归作者和博客园共有,欢迎围观转载.转载时请您务必在文章明显位置给出原文链接,谢谢您 ...
- Java垃圾回收机制[转]
原文地址:http://blog.csdn.net/zsuguangh/article/details/6429592 综合了若干人的blog- 1. 垃圾回收的意义 在C++中,对象所占的内存在程序 ...
- .NET垃圾回收机制(二)
一.GC的必要性 1.应用程序对资源操作,通常简单分为以下几个步骤:为对应的资源分配内存 → 初始化内存 → 使用资源 → 清理资源 → 释放内存. 2.应用程序对资源(内存使用)管理的方式,常见的一 ...
- Java垃圾回收机制(转)
原文链接:Java垃圾回收机制 1. 垃圾回收的意义 在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象:而在Java中,当没有对象引用指向原先分配给某个对象的内 ...
随机推荐
- Bootstrap Edit 使用方法
Getting Started <!-- rounded edit text --> <com.beardedhen.androidbootstrap.BootstrapEditTe ...
- hibernate关于一对一注解配置
注解(Annotation),也叫元数据.一种代码级别的说明.它是JDK1.5及以后版本引入的一个特性,与类.接口.枚举是在同一个层次.它可以声明在包.类.字段.方法.局部变量.方法参数等的前面,用来 ...
- Shell脚本入门学习笔记
1.shell操作系统和用户之间.负责解释命令行 2./etc/shells 记录登录系统有效支持shell 3./etc/passwd 最后,有人谁可以看到用户的默认shell 4.直接输入shel ...
- C# 特性的使用
using ClassLibrary;using System;using System.Collections.Generic;using System.Linq;using System.Refl ...
- 修改window.external使JS可调用Delphi方法
原文地址:http://hi.baidu.com/rarnu/blog/item/4ec80608022766d663d986ea.html 在js中,有一个比较特殊的对象,即window.exter ...
- nodejs timer block-timer timer-ease
https://www.npmjs.org/package/block-timer https://www.npmjs.org/package/timer-ease 来自为知笔记(Wiz)
- python3 无法使用flask.ext.* 报错的解决方法
python3 使用flask的一些扩展功能的导入方法是 from flask_bootstrap import Bootstrapfrom flask_moment import Momentfro ...
- Nancy Web框架
原文 Nancy Web框架 Nancy框架 一.创建第一个Nancy应用 二.探索Nancy的module 1. 模块能够在全局被发现 2. 使用模块为路由创建一个根 三.定义路由 1. 方法 2. ...
- Win8MetroC#数字图像处理--2.2图像二值化函数
原文:Win8MetroC#数字图像处理--2.2图像二值化函数 [函数代码] /// <summary> /// Binary process. /// </summary> ...
- Python杂谈: __init__.py的作用
我们经常在python的模块目录中会看到 "__init__.py" 这个文件,那么它到底有什么作用呢? 1. 标识该目录是一个python的模块包(module package ...