Explanation of single thread and multi thread use of timer timer in NET Framework

  • 2021-07-18 07:43:47
  • OfStack

If you need to repeat one method at regular intervals, the easiest way is to use a timer (timer). Compared with the following example, the timer can use memory and resources conveniently and efficiently:


new Thread (delegate() {
             while (enabled)
             {
              DoSomeAction();
              Thread.Sleep (TimeSpan.FromHours (24));
             }
            }).Start();

Not only will this take up one thread permanently, but without extra code, DoSomeAction will happen later every day. The timer solves these problems.

NET Framework provides four kinds of timers. The following two classes are generic multithreaded timers:

(1) System. Threading. Timer
(2) System. Timers. Timer
The other two are dedicated single-threaded timers:

(3) System. Windows. Forms. Timer (timer for Windows Forms)
(4) System. Windows. Threading. DispatcherTimer (timer for WPF)
Multi-threaded timers are more powerful, precise, and flexible, while single-threaded timers are safe and convenient for simple tasks of updating Windows, Forms, and WPF controls.

1. Multithreaded timer Permalink

System. Threading. Timer is the simplest multithreaded timer: It has only one constructor and two common methods (pleasing to minimalists, and the author of this book!) . In the following example, a timer calls the Tick method after 5 seconds to print "tick …" and then once per second until the user presses Enter:


using System;
using System.Threading;

class Program
{
 static void Main()
 {
  //  First interval  5000ms The interval after  1000ms
  Timer tmr = new Timer (Tick, "tick...", 5000, 1000);
  Console.ReadLine();
  tmr.Dispose();     //  Stop the timer and perform the cleanup 
 }

 static void Tick (object data)
 {
  //  This runs in the 1 Thread pool threads 
  Console.WriteLine (data);     //  Print  "tick..."
 }
}

You can then change the timer interval by calling the Change method. If you want the timer to fire only once, you can specify Timeout. Infinite as the last parameter of the constructor.

NET Framework provides another timer class with the same name under the System. Timers namespace. It simply encapsulates System. Threading. Timer and provides additional convenience while using exactly the same underlying engine. The following is a brief introduction to the added features:

(1) Component is implemented and allowed to be used in the designer of Visual Studio.
(2) The Interval attribute replaces the Change method.
(3) The Elapsed event replaces the callback delegate.
(4) The Enabled attribute is used to start or stop the timer (the default is false).
(5) Start and Stop methods to avoid confusion about Enabled attributes.
(6) AutoReset identity to specify whether it is a repeatable event (default is true).
The SynchronizingObject property provides Invoke and BeginInvoke methods to safely invoke methods on WPF and Windows Forms controls.
Here's an example:


using System;
using System.Timers;  //  Namespace is  Timers  Instead of  Threading

class SystemTimer
{
 static void Main()
 {
  Timer tmr = new Timer();    //  No parameters are required 
  tmr.Interval = 500;
  tmr.Elapsed += tmr_Elapsed;  //  Use events instead of delegates 
  tmr.Start();          //  Start the timer 
  Console.ReadLine();
  tmr.Stop();          //  Stop timer 
  Console.ReadLine();
  tmr.Start();          //  Restart timer 
  Console.ReadLine();
  tmr.Dispose();         //  Permanent stop timer 
 }

 static void tmr_Elapsed (object sender, EventArgs e)
 {
  Console.WriteLine ("Tick");
 }
}

Multithreaded timers use thread pools to allow a small number of threads to serve multiple timers. This means that callback methods or Elapsed events may be fired on different threads at a time. In addition, Elapsed always triggers almost on time regardless of whether the previous Elapsed completes execution or not. Therefore, the callback method or event handler must be thread-safe.

The accuracy of the multithreaded timer depends on the operating system and is typically in the range of 10-20 ms. If you need higher accuracy, you can use local interoperability (native interop) to call the Windows multimedia timer, which can improve the accuracy to 1 ms. It is defined in winmm. dll, first calling timeBeginPeriod to inform the operating system that you need higher timer precision, and then calling timeSetEvent to start the multimedia timer. When used, call timeKillEvent to stop the timer, and finally call timeEndPeriod to inform the operating system that you no longer need higher timer precision. A complete example can be found online by searching for the keyword dllimport winmm. dll timesetevent.

2. Single-threaded timer Permalink

. NET Framework provides two timers designed to eliminate thread safety issues in WPF and Windows Forms applications:

System. Windows. Threading. DispatcherTimer (WPF)
System. Windows. Forms. Timer (Windows Forms)
Single-threaded timers are not designed to work outside their specific environment. For example, if you use the Windows Forms timer in an Windows system service application, the Timer event does not fire!

Their exposed members are all like System. Timers. Timer1 (Interval, Tick, Start, and Stop) and are used similarly. But the difference lies in how it works internally. Instead of using thread pools to generate timer events, the WPF and Windows Forms timers rely on the underlying message loop mechanism of the UI model (message pumping mechanism). Means that the Tick event is always fired on the same thread that created the timer, which, in a normal program, is the same thread that manages all UI elements and controls. There are many advantages to this:

Single-threaded timers are safer and more convenient for simple tasks such as updating Windows Forms controls or WPF. An SynchronizingObject object that safely invokes a method in WPF or Windows Forms.
Single-threaded timers are timers designed to belong to their execution environment. If you use Timer of Windows Forms in an Windows service application, timer events will not be triggered, but will only be triggered in the corresponding environment.
Like System. Timers. Timer1, they also provide the same members (Interval, Tick, Start, Stop), but their internal working principles are different. The timers of WPF and Windows Forms use message looping mechanism instead of the thread pool to generate messages.

You don't have to think about thread safety.
The new Tick will not trigger until the previous Tick completes execution.
You can update the UI control directly in the Tick time event processing code, without calling Control. Invoke or Dispatcher. Invoke.
This sounds incredible until you realize that programs that use these timers are not really multithreaded and will not execute in parallel. One thread serves all timers and also handles UI events. This brings the disadvantage of single-threaded timer:

Unless the Tick event handler executes quickly, the UI will lose its response.
This makes the WPF and Windows Forms timers only suitable for small tasks, typically those that update the appearance of the UI (for example, display clocks or countdown). Otherwise, you need a multithreaded timer.

In terms of precision, single-threaded timers are similar to multithreaded timers (several 10 milliseconds), but are generally less precise because they are delayed by other UI requests (or other timer events).

The single-threaded timer is based on the Windows message loop, and the application processes the timer's messages synchronously. It will be found that the corresponding speed of UI interface is relatively slow. The solution to this problem is to use multithreaded timers.
Disadvantages of a single-threaded timer: Unless the Tick event handling code executes very fast, the UI interface becomes slow to respond. Therefore, the timers of WPF and Windows Forms are very suitable for small tasks, especially the task of updating the interface. Such as clock and count display. Otherwise, you need a multithreaded timer



Related articles: