詳解C#中的准時器Timer類及其渣滓收受接管機制。本站提示廣大學習愛好者:(詳解C#中的准時器Timer類及其渣滓收受接管機制)文章只能為提供參考,不一定能成為您想要的結果。以下是詳解C#中的准時器Timer類及其渣滓收受接管機制正文
關於C# Timer類 在C#裡關於准時器類就有3個
C# Timer應用的辦法1.界說在System.Windows.Forms裡
C# Timer應用的辦法2.界說在System.Threading.Timer類裡 "
C# Timer應用的辦法3.界說在System.Timers.Timer類裡
上面我們來詳細看看這3種C# Timer用法的說明:
(1)System.Windows.Forms.Timer
運用於WinForm中的,它是經由過程Windows新聞機制完成的,相似於VB或Delphi中的Timer控件,外部應用API SetTimer完成的。它的重要缺陷是計時不准確,並且必需有新聞輪回,Console Application(掌握台運用法式)沒法應用。
(2)System.Timers.Timer
和System.Threading.Timer異常相似,它們是經由過程.NET Thread Pool完成的,輕量,計時准確,對運用法式、新聞沒有特殊的請求。
(3)System.Timers.Timer還可以運用於WinForm,完整代替下面的Timer控件。它們的缺陷是不支撐直接的拖放,須要手工編碼。
C# Timer用法實例
應用System.Timers.Timer類 System.Timers.Timer t = new System.Timers.Timer(10000); //實例化Timer類,設置距離時光為10000毫秒; t.Elapsed += new System.Timers.ElapsedEventHandler(theout); //達到時光的時刻履行事宜; t.AutoReset = true; //設置是履行一次(false)照樣一向履行(true); t.Enabled = true; //能否履行System.Timers.Timer.Elapsed事宜; public void theout( object source, System.Timers.ElapsedEventArgs e) { MessageBox.Show("OK!"); }
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 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秒鐘挪用我們的回調辦法。