The difference of several timers in experience stack

Time:2021-2-27

catalog
  • 1. Preface
  • 2. Official introduction
  • 3. Personal experience
    • System.Threading.Timer Class
    • System.Windows.Forms.Timer Class
    • System.Timers.Timer Class
  • 4. Postscript
  • reference material

1. Preface

I don’t know if you have any questions about the timer in. Net. Here is a summary of Wu Xiaozhan.

2. Official introduction

Within the framework of. Net, there are four kinds of timers. First, let’s take a look at the official introduction of Microsoft to their respective characteristics

  • System.Timers.Timer , which triggers events and periodically executes code in one or more event sinks. Class is designed to be used as a server based component or service component in a multithreaded environment; it has no user interface and is not visible at run time.
  • System.Threading.Timer , which performs a single callback method on thread pool threads at regular intervals. The callback method is defined when the timer is instantiated and cannot be changed. And System.Timers.Timer Class is used as a server based or service component in a multithreaded environment; it has no user interface and is not visible at run time.
  • System.Windows.Forms . timer (net framework only), a Windows Forms component that triggers events and periodically executes code in one or more event sinks. Component has no user interface and is intended for use in a single threaded environment; it executes on UI threads.
  • System.Web.UI . timer (only. Net framework) is a method of periodically performing asynchronous or synchronous web postback ASP.NET Components.

Take another look at Microsoft’s suggestions for developers:

System.Threading.Timer Is a simple lightweight timer that uses callback methods and is serviced by thread pool threads. It is not recommended with windows forms because its callback does not occur on the user interface thread. System.Windows.Forms . timer is a better choice for Windows Forms. For server based timer functions, you can consider using System.Timers.Timer , which raises events and has other functions.

3. Personal experience

System.Threading.Timer Class

It’s a basic class. It’s not easy to use. Various usages are primitive and less used.

System.Windows.Forms.Timer Class

The first contact is it. After all, it’s OK to drag down WinForm directly. I usually use it to run some code to refresh the interface, which usually doesn’t have any logic operation, such as a countdown on the interface.

In the use of this class, I encountered two doubts, as a share:

Q1: will the tick practice create a new thread for execution?

A1: no new thread will be created, and the tick event will always be run in the main thread;

Q2: will the timer start() instantaneously, or wait for the interval before triggering?

A2: wait for the interval before triggering.

Q3: will interval accumulate when timer start() and stop()?

A3: do not accumulate. Start() will be repeated every time.

Q4: what happens if the code in the tick event is not executed, but the next tick timing has reached?

A4: the unfinished code will not be terminated by force, nor will it be triggered again because the last tick event code has not been executed. Instead, the unfinished code will be piled up in the form of stack. The code in the later triggered tick event will be executed first, and the unfinished code will be triggered before execution. For details, see the following example.

public Form1()
    {
        InitializeComponent();
        timerForm.Tick += TimerForm_Tick;
    }

    Private int num = 1; // a sequence number, indicating the number of the current tick event

    Private int rownum = 1; // a global line number. Record the total number of appendtext times

    private void TimerForm_Tick(object sender, EventArgs e)
    {
        
        String s = $"I am the {num + +} time";
        for (int i = 0; i < 5; i++)
        {
            Textbox1. Appendtext ($"{rownum + +} {s} ordinal I = {I} current thread ID={ Thread.CurrentThread.ManagedThreadId .ToString()} \r\n");
            Delay(1000);
        }
    }
    private Timer timerForm = new Timer(){Interval = 1000};
    private void button1_Click(object sender, EventArgs e)
    {
        textBox1.AppendText("button  " + Thread.CurrentThread.ManagedThreadId.ToString() + "\r\n");
        timerForm.Start();
    }
    public static void Delay(int mimillisecond)
    {
        int start = Environment.TickCount;
        while (Math.Abs(Environment.TickCount - start) < mimillisecond)
        {
            System.Windows.Forms.Application.DoEvents();
        }
    }

FormTimer

System.Timers.Timer Class

That’s right System.Threading.Timer The first layer of encapsulation of is to trigger timer events by callback through the delegate method timercallback. You can take a look first System.Timers.Timer The implementation of the code is as follows:

if (!value)
      {
        if (this.timer != null)
        {
          this.cookie = (object) null;
          this.timer.Dispose();
          this.timer = (System.Threading.Timer) null;
        }
        this.enabled = value;
      }
      else
      {
        this.enabled = value;
        if (this.timer == null)
        {
          if (this.disposed)
            throw new ObjectDisposedException(this.GetType().Name);
          int dueTime = (int) Math.Ceiling(this.interval);
          this.cookie = new object();
          this.timer = new System.Threading.Timer(this.callback, this.cookie, dueTime, this.autoReset ? dueTime : -1);
        }
        else
          this.UpdateTimer();
      }

however System.Threading.Timer The properties and methods of are more friendly. I usually use this timer class instead of designing an update interface. One thing to note is that after the synchronizingobject property is assigned to the control, the code in the event will delegate the call on the control, such as timer.SynchronizingObject = this; You can take a look System.Timers.Timer How is internal management realized.

if (elapsedEventHandler != null)
        {
          if (this.SynchronizingObject != null && this.SynchronizingObject.InvokeRequired)
          {
            this.SynchronizingObject.BeginInvoke(elapsedEventHandler, new object[]
            {
              this,
              elapsedEventArgs
            });
          }
          else
          {
            elapsedEventHandler(this, elapsedEventArgs);
          }
        }

Although System.Timers.Timer In theory, the timer is not limited by a single thread and can be triggered many times in a short time, but it is actually limited by the thread pool. Let’s see the explanation of giant hardware for this

IfnullSynchronizingobject property, the deleted event is raised on the ThreadPool thread. If the processed event lasts longer than interval, it may be raised again on other ThreadPool threads. In this case, the event handler should be reentrant.

1. When the synchronizingobject is not null, the event will be triggered on the specified object thread, which is a single thread trigger, and System.Windows.Forms The execution mode of. Timer is the same;

2. When the synchronizingobject is not null, an event is raised on the ThreadPool to execute the code in the event. Theoretically, it can be loaded repeatedly, but it is limited by the number of ThreadPool threads, such as ThreadPool.SetMaxThreads (8, 8), then the timer trigger event can only be loaded 8 times at the same time;

4. Postscript

I basically use timers now System.Timers.Timer In my opinion System.Timers.Timer You can use the synchronizingobject property to run in the main thread, or you can not set the synchronizingobject property. It is an event triggered in the thread pool. As a background thread, it can basically meet my needs in development.

reference material

System.Timers Namespace

System.Windows.Forms

System.Threading.ThreadPool Class