詳解C#中的定時(shí)器Timer類及其垃圾回收機(jī)制
關(guān)于C# Timer類 在C#里關(guān)于定時(shí)器類就有3個(gè)
C# Timer使用的方法1.定義在System.Windows.Forms里
C# Timer使用的方法2.定義在System.Threading.Timer類里 "
C# Timer使用的方法3.定義在System.Timers.Timer類里
下面我們來(lái)具體看看這3種C# Timer用法的解釋:
(1)System.Windows.Forms.Timer
應(yīng)用于WinForm中的,它是通過(guò)Windows消息機(jī)制實(shí)現(xiàn)的,類似于VB或Delphi中的Timer控件,內(nèi)部使用API SetTimer實(shí)現(xiàn)的。它的主要缺點(diǎn)是計(jì)時(shí)不精確,而且必須有消息循環(huán),Console Application(控制臺(tái)應(yīng)用程序)無(wú)法使用。
(2)System.Timers.Timer
和System.Threading.Timer非常類似,它們是通過(guò).NET Thread Pool實(shí)現(xiàn)的,輕量,計(jì)時(shí)精確,對(duì)應(yīng)用程序、消息沒有特別的要求。
(3)System.Timers.Timer還可以應(yīng)用于WinForm,完全取代上面的Timer控件。它們的缺點(diǎn)是不支持直接的拖放,需要手工編碼。
C# Timer用法實(shí)例
使用System.Timers.Timer類 System.Timers.Timer t = new System.Timers.Timer(10000); //實(shí)例化Timer類,設(shè)置間隔時(shí)間為10000毫秒; t.Elapsed += new System.Timers.ElapsedEventHandler(theout); //到達(dá)時(shí)間的時(shí)候執(zhí)行事件; t.AutoReset = true; //設(shè)置是執(zhí)行一次(false)還是一直執(zhí)行(true); t.Enabled = true; //是否執(zhí)行System.Timers.Timer.Elapsed事件; public void theout( object source, System.Timers.ElapsedEventArgs e) { MessageBox.Show("OK!"); }
Timer的垃圾回收機(jī)制
通常我們需要定時(shí)執(zhí)行一段任務(wù)的時(shí)候,我們就需要定時(shí)器,這時(shí)我們就可以使用c# System.Threading空間中的 Timer定時(shí)器;他是個(gè)異步定時(shí)器,時(shí)間到時(shí)每次都是在線程池中分配一個(gè)線程去執(zhí)行任務(wù)。下面我們來(lái)看一個(gè)有趣的例子:
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(); } }
當(dāng)我們?cè)赿ebug模式下運(yùn)行該段程序時(shí),正如我們期盼的那樣程序會(huì)每隔2秒鐘執(zhí)行該方法,打印出"in TimerCallback method”,而在release模式下執(zhí)行的時(shí)候,只執(zhí)行一次該方法,字符串只打印一次。在這里我們?cè)谡{(diào)用TimerCallback方法時(shí),強(qiáng)制執(zhí)行垃圾回收器,說(shuō)明在release模式下,垃圾回收器執(zhí)行回收算法時(shí),首先假設(shè)所有對(duì)象都是可回收的,當(dāng)將Timer對(duì)象賦值給變量t后,t沒有在被引用,因此也就沒有變量引用Timer對(duì)象,所以垃圾收集這時(shí)會(huì)回收Timer對(duì)象。那么為什么在debug模式下卻能夠運(yùn)行能,這跟c#編譯器的優(yōu)化方式有關(guān),在release模式下編譯器做了相關(guān)的優(yōu)化操作。而在debug模式下,timer對(duì)象的生成期是方法的結(jié)束,這樣做也是為了調(diào)試的方便。要不然在調(diào)試時(shí),我們執(zhí)行到Timer timer = new Timer()后想看timer的值時(shí),已經(jīng)被垃圾回收器給回收了,這是我們不期望看到的結(jié)果,編譯器如何處理的,我們可以看看編譯器在release模式下和debug模式下對(duì)上面的代碼編譯后生成的IL對(duì)比我們既知結(jié)果。
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對(duì)象的棧上的變量存放到局部變量0中。所以使得在debug模式下該t還被引用,不能夠回收Timer對(duì)象,所以也能出現(xiàn)我們期盼的結(jié)果,那么如何在兩種模式下都能得到我們期盼的結(jié)果呢。我們可以如下操作。
正確的代碼:
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(); } }
這時(shí)不管是在release模式下還是debug模式下,都會(huì)每隔2秒鐘調(diào)用我們的回調(diào)方法。
上一篇:C#中自定義高精度Timer定時(shí)器的實(shí)例教程
欄 目:C#教程
下一篇:C# MVC模式下商品抽獎(jiǎng)功能實(shí)現(xiàn)
本文標(biāo)題:詳解C#中的定時(shí)器Timer類及其垃圾回收機(jī)制
本文地址:http://mengdiqiu.com.cn/a1/C_jiaocheng/6541.html
您可能感興趣的文章
- 01-10C#中查找Dictionary中的重復(fù)值的方法
- 01-10C#將圖片存放到SQL SERVER數(shù)據(jù)庫(kù)中的方法
- 01-10C#中Socket通信用法實(shí)例詳解
- 01-10關(guān)于nancy中的身份驗(yàn)證
- 01-10C#中的事務(wù)用法實(shí)例分析
- 01-10C#裝箱和拆箱原理詳解
- 01-10C#類的多態(tài)性詳解
- 01-10C#創(chuàng)建不規(guī)則窗體的4種方式詳解
- 01-10C#實(shí)現(xiàn)讀取DataSet數(shù)據(jù)并顯示在ListView控件中的方法
- 01-10C#中深度復(fù)制和淺度復(fù)制詳解


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10C#通過(guò)反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁(yè)無(wú)法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實(shí)現(xiàn)txt定位指定行完整實(shí)例
- 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新
- 01-10C#停止線程的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#通過(guò)重寫Panel改變邊框顏色與寬度的
- 01-10C#實(shí)現(xiàn)讀取注冊(cè)表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機(jī)閱讀
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10C#中split用法實(shí)例總結(jié)
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10delphi制作wav文件的方法
- 04-02jquery與jsp,用jquery
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什