Differences and usage of the three Timer types in. NET and the use of. net timer types
Recently, a program is executed on a regular basis on the WEB, and. NET has three different timers. So it's just research. The three timers are:
// 1. Implement the timer for events triggered at user-defined intervals. This timer is most suitable for Windows Forms applications and must be used in Windows.
System. Windows. Forms. Timer
// 2. provides a mechanism for executing methods at a specified interval. This class cannot be inherited.
System. Threading. Timer
// 3. generate periodic events in the application.
System. Timers. Timer
The three timers are located in different namespaces. The above describes the usage of the three timers. The first one is a control that can only be used in Windows Forms. In. NET1.1, 3rd System. Timers. Timer can also be dragged and used, and. NET2.0 is canceled and can only be edited manually. The last two are not restricted. The following describes the usage and differences of the three timers through specific columns. There are many online discussions, but there is basically no code.
One System. Windows. Forms. Timer
# Region System. Windows. Forms. Timer
Public partial class Form1: Form
{
Public Form1 ()
{
InitializeComponent ();
}
Int num = 0;
Private void Form_Timer_Tick (object sender, EventArgs e)
{
Label1.Text = (++ num). ToString ();
Thread. Sleep (3000 );
}
Private void button#click (object sender, EventArgs e)
{
Form_Timer.Start ();
}
Private void button2_Click (object sender, EventArgs e)
{
Form_Timer.Stop ();
}
}
# Endregion
The above is a very simple function, dragging a System on the Form. windows. forms. the Timer control is named Form_Timer. In the Properties window, set the Enable attribute to true and Interval to the Timer Interval. Double-click this control to see the Form_Timer_Tick method. In this method, we asked her to constantly add a number and display it on the form. The two buttons provide the timer control function.
When executing the command, you click another form to return, and you will find that our form has no response. This is because we use Thread. Sleep (3000); to suspend the current Thread, and the UI loses the corresponding value. This shows that we use a single Thread for execution. That is, the thread that executes the timer is the UI thread.
Timer is used to trigger events at user-defined event intervals. The Windows timer is designed for a Single-threaded environment, where the UI thread is used for processing. It requires the user code to have an available UI message pump, and always operate in the same thread, or mail the call to another thread.
A Tick event is defined in Timer. When we double-click this control, a line of code is added.
This. Form_Timer.Tick + = new System. EventHandler (this. Form_Timer_Tick );
This should be clear. If you do not understand it, you can refer to the articles on delegation and events in my BLOG. Then, Windows associates the timer with the calling thread (UI thread ). When a timer is triggered, Windows inserts a timer message into the thread message queue. The Calling thread executes a message pump to extract the message and sends it to the callback method (the Form_Timer_Tick method here ). These are all performed in a single thread, so the UI will be suspended when the callback method is executed. Therefore, it is not recommended to use this control to execute code with limited computing or limited I/O, because this will easily lead to a false UI, and Timer called by multiple threads should be used. In addition, it should be noted that the time precision of this control is not high, and the precision is limited to 55 milliseconds. We set Interval to 20 ms, record the current time in the start and stop methods, and calculate the running time:
From the figure above, we can see that the program executes 7.8S, that is, 7800 ms, and the interval is 20 ms. That is, the last displayed number is about 390, but only 250, obviously, it is not accurate, but according to MSDN, the precision of 55 ms, 140 ms should only be executed more than times or less. I don't know if there is any problem here.
Two System. Timers. Timer
Next let's take a look at another Timer. We use it to rewrite the above program.
# Region System. Windows. Forms. Timer
Public partial class Form1: Form
{
Public Form1 ()
{
InitializeComponent ();
}
Int num = 0;
DateTime time1 = new DateTime ();
DateTime time2 = new DateTime ();
// Define Timer
System. Timers. Timer Timers_Timer = new System. Timers. Timer ();
Private void button#click (object sender, EventArgs e)
{
// Manually set Timer and start execution
Timers_Timer.Interval = 20;
Timers_Timer.Enabled = true;
Timers_Timer.Elapsed + = new System. Timers. ElapsedEventHandler (Timers_Timer_Elapsed );
Time1 = DateTime. Now;
}
Void Timers_Timer_Elapsed (object sender, System. Timers. ElapsedEventArgs e)
{
Label1.Text = Convert. ToString (++ num); // display to lable
Thread. Sleep (3000 );
}
Private void button2_Click (object sender, EventArgs e)
{
// Stop execution
Timers_Timer.Enabled = false;
Time2 = DateTime. Now;
MessageBox. Show (Convert. ToString (time2-time1 ));
}
}
# Endregion
We can see that this code is basically the same as the previous use of Form. Timer. The difference is that we define objects manually, rather than by pulling controls. It also has attributes such as Interval and Enabled, which serve the same purpose as the first one. The difference is that his event name is Elapsed, but like the above Tick, it binds a delegate method. But here we do it manually. The other difference is that we can use the Stop and Start methods to control Form. Timer, which is controlled by the Enable attribute. However, you can also use the Stop and Start methods, which are also controlled by its own Enable.
The biggest difference is that the above Code will report an error during debugging, prompting you "The Inter-thread operation is invalid: access it from a thread that is not creating the control" label1. "But if you run it without debugging, and you drag the form during running, you will find that there is no false death. Here we can know that the Timer creation thread and execution thread are not the same thread. That is, multithreading is used. The creation thread of Timer is the UI thread, and the execution thread is the thread in TheardPool, so it will not be suspended, but an error will be reported during debugging, because the creation thread of non-control cannot operate the control. But you can run it directly. Here, VS05 is used. There are many solutions, such as delegate. BeginInvoke. This article introduces a unique method to set the SynchronizingObject attribute of Timer, Timers_Timer.SynchronizingObject = label1. In this way, we will not report an error during debugging and running, however, if Timer is set, a single-thread call is programmed, which is basically the same as the first one.
Timer is designed for auxiliary threads in a multi-threaded environment. The server timer can be moved between threads to process the triggered Elapsed event, so that the event can be triggered more accurately than the Windows timer. The Elapsed event is triggered on the ThreadPool thread. If the processing time of the Elapsed event is longer than Interval, the event will be raised again in another ThreadPool thread. Therefore, the event handler should be reentrant.
In addition, it is different from the previous phenomenon that after each addition of 1, the display does not stop for 3 seconds. It continues to display, but the speed is a little slow. Because the interval is set to 20 ms and the execution time is 3 s, the execution will continue in another thread after 20 ms, and the current thread will be suspended. About the timer precision, cancel the 3 s suspension and find that the result is basically the same as the first one.
3. System. Threading. Timer
Continue to use this object transformation program.
# Region System. Windows. Forms. Timer
Public partial class Form1: Form
{
Public Form1 ()
{
InitializeComponent ();
}
Int num = 0;
DateTime time1 = new DateTime ();
DateTime time2 = new DateTime ();
System. Threading. Timer Thread_Time;
Private void button#click (object sender, EventArgs e)
{
// Start
Thread_Time = new System. Threading. Timer (Thread_Timer_Method, null, 0, 20 );
Time1 = DateTime. Now;
}
Void Thread_Timer_Method (object o)
{
Label1.Text = Convert. ToString (++ num ));
System. Threading. Thread. Sleep (3000 );
}
Private void button2_Click (object sender, EventArgs e)
{
// Stop
Thread_Time.Dispose ();
Time2 = DateTime. Now;
MessageBox. Show (Convert. ToString (time2-time1 ));
}
}
# Endregion
The Threading. Timer method is not the same as the preceding method. Therefore, all parameters are set in the constructor and the start time can be set. The start and stop methods are not provided to control the timer. It is implemented in a callback method instead of an event. There is a difference between them.
We only need to destroy the object to stop it. When you run it, you will find that it is the same as Timers. Timer in front, it is multi-threaded, mainly because it will not be suspended, and debugging and running reports an error. But what surprised you was that our code could not stop her. It is useless to call the Dispose method. Where is the problem? Then a test was conducted and the interval was modified to 100,200,500,100, 4000. These situations. It is found that when the interval is more than ms, it is basically stopped immediately. The shorter the execution interval, the longer the execution interval. This should be caused by running multiple threads when the interval is less than the execution time. Because all threads do not stop at the same time. The shorter the interval, the more threads, the more execution times.
Finally, let's look at another special place for this object.
Static void Main ()
{
Timer t = new Timer (Test, null, 0,1000 );
Console. ReadLine ();
}
Public static void Test (object o)
{
Console. WriteLine ("nihao ");
GC. Collect ();
}
What results will this code output? By default, it only outputs the output once and stops. Why? According to the above description, after defining the object t and executing the code, forced garbage collection is performed, because t has no other references in Main, so it is recycled. But if we cancel the "optimization" item of the compiler, check the situation. The program is always output. Why is garbage collection not collected? Because the optimization option is disabled, the declaration period of t is extended to the end of the method. So keep running.
Because the compiler is optimized by default, we must ensure that the Timer object is always referenced to avoid garbage collection. Therefore, when the compiler enables optimization, t = null is added at the end of the Main function to ensure that it is referenced before collection. However, this is useless. The JIT compiler will delete t = null directly after optimization, so we can use t. Dispose () to achieve the goal. During garbage collection, CLR found that t was still referenced and Dispose was not executed. It is a case where Threading. Timer sometimes stops running once or is destroyed and still running. It is also related to compiler optimization, so pay attention to it during use.
Finally, let's take a look at the description of MSDN: as long as you are using Timer, you must keep the reference to it. If there is no reference to Timer for any managed object, the Timer will be reclaimed. Timer is recycled even if it is still active. When you no longer need a timer, use the Dispose method to release the resources held by the timer. If you want to receive a signal when the timer is released, use the Dispose (WaitHandle) method that accepts WaitHandle to overload it. After the timer is released, WaitHandle is terminated.
Summary:
System. Threading. Timer is a simple lightweight Timer that uses the callback method and is provided by the thread pool thread. It is not recommended to use Windows Forms because the callback is not performed on the user interface thread. System. Windows. Forms. Timer is a better choice for Windows Forms. To obtain the server-based Timer function, consider using System. Timers. Timer, which can trigger events and have other functions.
In CLR Via C #, the three timers are mentioned in multithreading, but the author says System. timers. timer is for System. threading. timer reporting is not recommended, but I still use this in Application_Start IN MY WEB Project instead of Threading. timer, because Threading. when Timer is executed only once, it will not be executed.
The usage of the timer in the B/S structure is more complicated. Generally, we put the timer in Application_OnStart. In this way, a global timer can be maintained to regularly back up the database and regularly maintain users, in addition, the method is static to avoid garbage collection. It is not recommended to use it in general aspx pages, because the server-side timer is of little significance to users and can be replaced by JS. In addition, each request on this page may introduce a new timer, resulting in system crash. In addition, the timer is an ASP. NET process, which is related to IIS. Therefore, we recommend that you write services or independent programs as important execution tasks on the server for execution.
C # differences between the three timer types
In C #, there are three timer classes.
1. defined in System. Windows. Forms
2. defined in the System. Threading. Timer class
3. defined in the System. Timers. Timer class
System. Windows. Forms. Timer is used in WinForm. It is implemented through the Windows message mechanism. Similar to the Timer control in VB or Delphi, it is implemented using the API SetTimer internally. Its main disadvantage is that the timing is not accurate and there must be a message loop, which cannot be used by the Console Application.
System. Timers. Timer and System. Threading. Timer are very similar. They are implemented through the. NET Thread Pool. They are lightweight and time-precise, and have no special requirements on applications and messages. System. Timers. Timer can also be used in WinForm to completely replace the above Timer control. Their disadvantage is that they do not support direct drag and drop and require manual encoding.
Example:
Use the System. Timers. Timer class
System. Timers. Timer t = new System. Timers. Timer (10000); // instantiate the Timer class and set the interval to 10000 milliseconds;
T. Elapsed + = new System. Timers. ElapsedEventHandler (theout); // execute the event at the time of arrival;
T. AutoReset = true; // set whether to execute once (false) or always execute (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! ");
}
NET!
In fact, there is nothing to say about it. Just open MSDN and read it.
System. Windows. Forms: implements the timer that triggers events at user-defined intervals. This timer is most suitable for Windows Forms applications and must be used in Windows.
Windows form Timer is a single-threaded component with a precision of 55 ms. If you need a more precise multi-thread Timer, use the Timer class in the System. Timers namespace.
System. Threading. Timer is a simple lightweight Timer that uses the callback method and is provided by the thread pool thread. It is not recommended to use Windows Forms because the callback is not performed on the user interface thread. System. Windows. Forms. Timer is a better choice for Windows Forms. To obtain the server-based Timer function, consider using System. Timers. Timer, which can trigger events and have other functions.
System. Timers: the Timer component is a server-based Timer that allows you to specify the periodic interval at which Elapsed events are triggered in an application. This event can then be manipulated to provide regular processing. Generate periodic events in the application. Server-based Timer is designed for auxiliary threads in multi-threaded environments. The server timer can be moved between threads to process the triggered Elapsed event, so that the event can be triggered more accurately than the Windows timer.