關於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用法實例
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19使用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秒鐘調用我們的回調方法。