About the C # timer class in C # about the Timer class there are 3
Method used by C # timer 1. defined in System.Windows.Forms
Method used by C # timer 2. defined in the System.Threading.Timer class "
Method used by C # timer 3. defined in the System.Timers.Timer class
Let's take a concrete look at the explanations of these 3 C # timer usages:
(1) System.Windows.Forms.Timer
Applied to WinForm, it is implemented through the Windows Messaging mechanism, similar to the Timer control in VB or Delphi, which is implemented internally using API SetTimer. Its main disadvantage is that the timing is imprecise and that there must be a message loop that the console application (console application) cannot use.
(2) System.Timers.Timer
Very similar to System.Threading.Timer, they are implemented through the. NET Thread Pool, lightweight, timed accurately, with no special requirements for applications or messages.
(3) System.Timers.Timer can also be applied to WinForm to completely replace the timer control above. Their disadvantage is that they do not support direct drag-and-drop and require manual coding.
C # Timer Usage example
Use the System.Timers.Timer class
System.Timers.Timer t =
new System.Timers.Timer (10000);
Instantiate the Timer class, set the interval to 10000 milliseconds,
t.elapsed + +
new System.Timers.ElapsedEventHandler (theout);
Execute event at time of arrival;
T.autoreset = true;
Whether the setting is executed once (false) or always (true);
t.enabled = true;
Whether to execute the System.Timers.Timer.Elapsed event; public
void Theout (
object source,
System.Timers.ElapsedEventArgs e)
{
MessageBox.Show ("ok!");
}
Timer's garbage collection mechanism
usually when we need to perform a task on a regular basis, we need the timer, and then we can use the timer timer in C # system.threading space; he's an asynchronous timer, and every time it's a thread in the threads pool to perform the task. Let's take a look at an interesting example here:
Class program
{
static void Main (string[] args)
{
Timer timer = new timer (timercallback,null,0,2000); C5/>console.readline ();
}
private static void TimerCallback (object o)
{
Console.WriteLine ("In TimerCallback Method");
Gc. Collect ();
}
When we run the program in debug mode, as we expect, the program executes the method every 2 seconds, prints out "in TimerCallback method", and executes it only once in release mode, and the string is printed only once. In this case, when we call the TimerCallback method, we force the garbage collector to say that in release mode, the garbage collector performs the recycle algorithm, first assuming that all objects are recyclable, and that T is not referenced after assigning the timer object to the variable T. Therefore there is no variable referencing the timer object, so garbage collection then reclaims the Timer object. So why is the ability to run in debug mode, which is related to the C # compiler optimization, in release mode, the compiler did the relevant optimization operation. In debug mode, the timer object generation period is the end of the method, which is also convenient for debugging. Otherwise, when we run to the timer timer = new timer () and want to see the timer's value when we are debugging, we have been recycled by the garbage collector, which is what we do not expect to see, and how the compiler handles it, We can see how the compiler compares the IL generated after compiling the above code in release mode and in debug mode. We know the result.
Release mode compilation generated IL:
. method private Hidebysig static void Main (string[] args) cil managed
{
. entrypoint
/Code size (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
Il generated in debug mode:
method private hidebysig static void Main (string[) args) cil managed {. entrypoint/ /Code size 0x21. maxstack 4 Locals init ([0] class [Mscorlib]system.threading.timer Timer) Il_0000:nop il_0 001: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:l dc.i4.0 IL_000f:ldc.i4 0x7d0 il_0014:newobj instance void [Mscorlib]system.threading.timer::.ctor (class [mscorlib] System.Threading.TimerCallback, Object, Int3 2, Int32) il_0019:stloc.0 il_001a:call string [mscorlib]system.console::read Line () Il_001f:pop Il_0020:ret}//End of method Program::main
From the generated IL we can see that in debug mode, IL is generated more than 19 lines of red font in release mode, which is used to store the variables on the stack of 15 rows that reference the timer object to local variable 0. So in debug mode the T is also referenced, can not recycle timer object, so can also appear we expect results, then how in both modes can get the results we expect. We can do the following.
The correct code:
Class program
{
static void Main (string[] args)
{
Timer timer = new timer (timercallback,null,0,2000); C5/>console.readline ();
Timer. Dispose ();
}
private static void TimerCallback (object o)
{
Console.WriteLine ("In TimerCallback Method");
Gc. Collect ();
}
In either release mode or debug mode, our callback method is invoked every 2 seconds.