你需要知道的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中,当没有对象引用指向原先分配给某个对象的内 ...
随机推荐
- quick-cocos2d-x游戏开发【8】——动画与动作
动画与动作,在quick中都有对其封装,所以我们还是来看一下吧. 总的来说,对于帧动画,quick封装的方法我们能够常常使用,这是很方便的,以下直接上代码来直观感受下, 比方,14张帧图片,採用coc ...
- 《TIME》时代周刊阅读
0. 常识 tribunal 是解决民事诉讼和民事纠纷的地方,以调解为主,使用主席制.主席是受过司法培训,具有一定法律基础的,但不能像法官一样直接给你判决,也不能强制执行. Court 一般针对严重案 ...
- SQLite介绍及使用
SQLite,是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了 ...
- 不使用运算符(+、-、*、/) 来进行四则运算(C#)
最近在LeetCode 上刷题,遇到一个非常有趣的题目,题目的大概意思就是在不使用运算符的情况下实现两个数的加法...原题点这里>>> 说实话,刚看到这题目,我是一脸懵逼的. 后来仔 ...
- HTML5 课程
http://www.w3school.com.cn/html5/html_5_geolocation.asp HTML5 教程 HTML5 教程 HTML5 简单介绍 HTML5 视频 HTML5 ...
- 百度最热门31款开源项目:ECharts火爆了!
本文为大家整理了百度开源的热门项目,看看有没有感兴趣的,排名顺序按照 Github ★Star 数排列. 0.一个纯 Java 的图表库 ECharts★Star 19690 ECharts,一个纯 ...
- python_简单的DB统计
import numpy as npimport pylab as pldates=['20170314','20170315','20170316','20170317','20170318','2 ...
- Goutte 获取http response
$client = new Goutte\Client(); $crawler = $client->request('GET', 'http://symfony.com'); 获取http 响 ...
- 线程操纵UI问题
WPF只允许UI线程修改UI,其他线程必须通过Invoke.委托(安全性)Winform可以开启/关闭“只允许UI线程修改UI” 在WPF中非UI线程修改UI的方法 非UI线程直接修改UI,会报错 S ...
- 开源数据源使用 DBCP 和 C3PO
jar包: commons-dbcp-1.4.jar commons-pool-1.5.6.jar mysql-connector-java-5.0.8-bin.jar 建立dbcp的配置文件 dbc ...