C# timer package version

I. Overview

In the development of platforms such as Winform, the timer function is often used, but once the project timer is written too much, it is easy to cause the software to become stuck, and the running time will cause the software to crash. This may be caused by memory overflow. , I didn’t go into the specific reasons. The other one is that when you close the software, you often can’t close it, because the thread of the timer is still running at this time. You have to close these timers one by one to close the software. Or directly use the forced exit program code, which is very troublesome. Later, I wonder if I can encapsulate a timer and use the event subscription mechanism to realize the functions. These functions will be realized later, so let’s start moving the code below.

Two, realize the function

Create a new winform project and add a class ScanTimer.cs.

code:

using System;
using System.Threading;

/// <summary>
/// 定时器
/// </summary>
public class ScanTimer
{
    /// <summary>
    /// 定时器回调事件
    /// </summary>
    public static event Action ScanEvent;
    /// <summary>
    /// 定时器开关的状态
    /// </summary>
    public static Action<bool> TimerStatus = null;
    /// <summary>
    /// 定时器执行的次数
    /// </summary>
    public static Action<int> TimerExecuteCount = null;

    /// <summary>
    /// 定时器是否打开
    /// </summary>
    public static bool IsOpen
    {
        get
        {
            if (Timer == null)
                return false;
            return Timer.Enabled;
        }
    }

    //定时器
    private static System.Timers.Timer Timer = null;
    //间隔时间
    private const int IntervalTime = 2000;
    //定时清理控制台日志
    private static int OutCount = 0;
    //是否初始化
    private static bool IsInit = false;


    /// <summary>
    /// 初始化
    /// </summary>
    private static void Init()
    {
        //实例化Timer类,
        Timer = new System.Timers.Timer();
        //设置间隔时间(毫秒);
        Timer.Interval = IntervalTime;
        //到达时间的时候执行事件;
        Timer.Elapsed += new System.Timers.ElapsedEventHandler(Elapsed);
        //设置是执行一次(false)还是一直执行(true);
        Timer.AutoReset = true;

        IsInit = true;
    }

    /// <summary>
    /// 定时器
    /// </summary>
    /// <param name="source"></param>
    /// <param name="e"></param>
    private static void Elapsed(object source, System.Timers.ElapsedEventArgs e)
    {
        OutCount++;
        if (OutCount > 10000)
        {
            OutCount = 0;
            //Console.Clear();
        }

        //定时器的执行次数
        if (TimerExecuteCount != null)
            TimerExecuteCount(OutCount);

        //执行回调
        if (ScanEvent != null)
            ScanEvent();
    }

    /// <summary>
    /// 打开定时器
    /// </summary>
    public static void Start()
    {
        if (!IsInit) Init();

        Timer.Enabled = true;
        OutCount = 0;

        if (TimerStatus != null)
            TimerStatus(true);
    }

    /// <summary>
    /// 关闭定时器
    /// </summary>
    public static void Stop()
    {
        Timer.Enabled = false;
        OutCount = 0;

        if (TimerStatus != null)
            TimerStatus(false);
    }

    /// <summary>
    /// 清除所有的事件
    /// </summary>
    public static void ClearAllEvent()
    {
        if (ScanEvent == null) return;
        Delegate[] dels = ScanEvent.GetInvocationList();
        foreach (Delegate del in dels)
        {
            ScanEvent -= del as Action;
        }
        Console.WriteLine("[ClearAllEvent]清除定时器所有的事件");
    }

    /// <summary>
    /// 获取定时器任务的个数
    /// </summary>
    /// <returns></returns>
    public static int GetTaskCount()
    {
        if (ScanEvent == null) return 0;
        Delegate[] dels = ScanEvent.GetInvocationList();
        return dels.Length;
    }

    /// <summary>
    /// 是否存在某个任务
    /// </summary>
    /// <param name="taskName"></param>
    /// <returns></returns>
    public static bool IsExistTask(string taskName)
    {
        if (ScanEvent == null)
            return false;

        Delegate[] dels = ScanEvent.GetInvocationList();
        foreach (Delegate del in dels)
        {
            object delObj = del.GetType().GetProperty("Method").GetValue(del, null);
            string funcName = (string)delObj.GetType().GetProperty("Name").GetValue(delObj, null);
            if (funcName == taskName) return true;
        }

        return false;
    }


    private ScanTimer() { }
}

Add Form1_Load and Form1_FormClosing events to the Form1 form.

The Form1_Load event is executed once when the form starts, and the timer can be started here.

The Form1_FormClosing event is executed once when the form is closed, where we can turn off the timer.

As shown below:

 

3. Test

The ScanEvent field of ScanTimer is an event, and this is where we need to add a subscription mechanism.

public static event Action ScanEvent;

In fact, the principle is also very simple, that is, encapsulate a timer in the ScanTimer class, execute this event every few seconds, and then all methods for subscribing to this event will be executed.

Before calling the ScanTimer class, first change the output type of winform to console application, which is more convenient for observation.

code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace 定时器
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ScanTimer.ScanEvent += Timer;

            ScanTimer.Start();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            ScanTimer.Stop();
        }

        private void Timer()
        {
            Console.WriteLine("定时器");
        }
    }
}

The call is also very simple, just write a Timer() method, and then add it to the ScanEvent event, let's run it to see the effect

In addition, I also encapsulate other methods in the ScanTimer class. For example, you don’t know whether the timer is still executing. Sometimes the code is executed, and you don’t necessarily need to print it in the code. You can use the TimerExecuteCount delegate to check the execution of the timer. How many times, you can also use the TimerStatus delegate to check whether the timer is executing.

code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace 定时器
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            ScanTimer.ScanEvent += Timer;
            ScanTimer.TimerStatus += TimerStatus;
            ScanTimer.TimerExecuteCount += TimerExecuteCount;

            ScanTimer.Start();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            ScanTimer.Stop();
        }

        private void Timer()
        {
            Console.WriteLine("定时器");
        }

        private void TimerStatus(bool sw)
        {
            Console.WriteLine("定时器的状态:{0}", sw);
        }

        private void TimerExecuteCount(int count)
        {
            Console.WriteLine("定时器执行次数:{0}", count);
        }
    }
}

run:

Here, the two delegates TimerExecuteCount and TimerStatus are Action types. If other classes do not need to subscribe to these two delegates, you don’t need to use +=, you can directly use the = sign.

ScanTimer.ScanEvent += Timer;
ScanTimer.TimerStatus = TimerStatus;
ScanTimer.TimerExecuteCount = TimerExecuteCount;

 

Finish

If this post is helpful to you, please pay attention, like and leave a message

end

Guess you like

Origin blog.csdn.net/qq_38693757/article/details/131979981