C# 三种定时器的用法

目录

1.System.Timers.Timer

2.System.Windows.Forms.Timer

3.System.Threading.Timer

4.简单的封装


这里介绍三种常用的定时器,方便查阅资料或直接复制使用。

1.System.Timers.Timer

System.Timers.Timer 类定义了一个计时器,该计时器按固定间隔触发事件。它主要用于多线程环境,特别是在基于服务器的组件或服务组件中。此类没有用户界面,在运行时不可见,特别适用于后台任务处理。

主要属性和方法

  • Interval:以毫秒为单位,设置或获取引发 Elapsed 事件的时间间隔。
  • AutoReset:设置或获取一个值,该值指示计时器在 Elapsed 事件触发后是否自动重置,并继续计时(true)或停止计时(false)。
  • Enabled:设置或获取一个值,该值指示计时器是否已启用(true)或已禁用(false)。
  • Start():通过将 Enabled 设置为 true 来启动计时器。
  • Stop():通过将 Enabled 设置为 false 来停止计时器。
  • Elapsed 事件:当指定的时间间隔过去时,将触发此事件。该事件处理函数在新的线程中执行,因此不能直接访问UI控件(需通过委托和Invoke方法)。

使用场景

适用于需要按固定时间间隔执行任务的后台服务或应用程序,如定期检查数据库、更新状态信息等。

用法:

namespace Test2
{
    internal class Program
    {
        private static System.Timers.Timer Timer;
        static void Main(string[] args)
        {
            Timer = new System.Timers.Timer();
            Timer.Interval = 2000; //间隔时间2000毫秒
            Timer.AutoReset = true;//是否重复执行
            Timer.Elapsed += Timer_Elapsed;
            Timer.Enabled = true; //或者使用 Timer.Start() 效果一样

            Console.ReadKey();
        }

        private static void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            Console.WriteLine("需要重复执行的代码");
        }
    }
}

2.System.Windows.Forms.Timer

System.Windows.Forms.Timer 控件是Windows窗体环境中的定期事件引发组件。它主要用于单线程环境,特别是在UI更新中。该计时器是同步的,意味着它在UI线程上执行,不会阻塞或干扰UI操作。

主要属性和方法

  • Interval:以毫秒为单位,设置或获取计时器事件之间的时间间隔。
  • Enabled:设置或获取一个值,该值指示计时器是否已启用(true)或已禁用(false)。
  • Start():启动计时器。
  • Stop():停止计时器。
  • Tick 事件:当指定的时间间隔过去时,将触发此事件。与 System.Timers.Timer 不同,Tick 事件在UI线程上执行,因此可以直接访问UI控件。

使用场景

适用于需要按固定时间间隔更新UI元素的场景,如时钟、动画、进度条更新等。

System.Windows.Forms.Timer 可以在 Winform 工具箱中直接拖入到 Winform 界面中,也可以直接在代码中添加,System.Windows.Forms.Timer 在定时器回调中可以调用 Winform 的界面控件,而 System.Timers.Timer 回调内使用 Winform 控件会存在跨线程的错误。

用法同 System.Timers.Timer 差不多,用工具箱中的 Timer 可以少写很多代码。

代码:

using System;
using System.Windows.Forms;

namespace Test1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        System.Windows.Forms.Timer Timer;

        private void Form1_Load(object sender, EventArgs e)
        {
            Timer = new System.Windows.Forms.Timer();
            Timer.Interval = 1000;
            Timer.Tick += Timer_Tick;
            Timer.Start();
        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            Console.WriteLine("需要重复执行的代码");
        }
    }
}

3.System.Threading.Timer

System.Threading.Timer 类由线程池调用,专门用于在线程池线程上按固定间隔执行单个回调方法。它是为服务器或后台应用程序设计的,可以优化系统资源的使用。

主要属性和方法

  • Callback:定义在指定时间间隔后调用的回调方法。
  • State:传递给回调方法的对象,作为回调方法的参数。
  • DueTime:计时器第一次触发之前延迟的时间(以毫秒为单位)。
  • Period:计时器每次触发之间的时间间隔(以毫秒为单位)。设置为 Timeout.Infinite 表示计时器只触发一次。
  • Change(Int64, Int64):在计时器启动后更改其 DueTime 和 Period 设置。
  • Dispose():释放 Timer 对象使用的资源。

使用场景

适用于需要定期执行长时间运行或资源密集型任务的后台应用程序,如文件清理、数据同步等。由于回调方法在线程池线程上执行,因此不会影响UI线程的性能。

代码:

namespace Test2
{
    internal class Program
    {
        private static System.Threading.Timer Timer;
        static void Main(string[] args)
        {
            //参数1 要定时执行的回调
            //参数2 定时回调的参数
            //参数3 延迟多少秒开始执行
            //参数4 定时器的间隔时间
            Timer = new System.Threading.Timer(OnTimedEvent, null, 0, 1000);

            Console.ReadKey();
        }

        private static void OnTimedEvent(Object state)
        {
            Console.WriteLine("需要重复执行的代码");
        }
    }
}

可以使用下面的方法来停止定时器

// 暂时停止定时器
Timer.Change(Timeout.Infinite, Timeout.Infinite);

如果需要继续执行定时器,可以使用下面的方法

// 重新启动定时器:初始延迟1000毫秒,每2000毫秒触发一次
Timer.Change(1000, 2000);

其实还有一个定时器 System.Web.UI.Timer,只是现在用的人比较少,这里就不做介绍了。

4.简单的封装

根据上面的代码可以发现,就那几行代码,复制来复制去的有点麻烦,我这里稍微封装一下,一句代码搞定定时器,非常的方便。

新建一个类 TimerScheduler

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

/// <summary>
/// 定时器的封装
/// </summary>
public class TimerScheduler
{
    private static Dictionary<string, ActionSchedulerInfo> SchedulerDic = new Dictionary<string, ActionSchedulerInfo>();

    /// <summary>
    /// 添加定时执行委托
    /// </summary>
    /// <param name="key">唯一的Key</param>
    /// <param name="intervalInSeconds">定时器间隔时间</param>
    /// <param name="isUIThread">是否是UI线程</param>
    /// <param name="action">定时器回调</param>
    public static void Add(string key, double intervalInSeconds, bool isUIThread, Action action)
    {
        if (action == null)
        {
            Console.WriteLine("参数 action 不能为空");
            return;
        }
        if (string.IsNullOrEmpty(key))
        {
            Console.WriteLine("参数 key 不能为空");
            return;
        }
        if (SchedulerDic.ContainsKey(key))
        {
            Console.WriteLine($"{key} 不能重复的添加");
            return;
        }
        if (intervalInSeconds <= 0 || intervalInSeconds > 86400)
        {
            Console.WriteLine($"{key} 的间隔时间超过了指定的范围");
            return;
        }

        var actionScheduler = new ActionSchedulerInfo();
        if (isUIThread)
        {
            actionScheduler.timerUI = new System.Windows.Forms.Timer();
            actionScheduler.timerUI.Interval = (int)TimeSpan.FromSeconds(intervalInSeconds).TotalMilliseconds;
            actionScheduler.timerUI.Tick += (sender, e) => action();
            actionScheduler.timerUI.Start();
        }
        else
        {
            actionScheduler.timer = new System.Timers.Timer();
            actionScheduler.timer.Interval = TimeSpan.FromSeconds(intervalInSeconds).TotalMilliseconds;
            actionScheduler.timer.Elapsed += (sender, e) => Task.Run(action);
            actionScheduler.timer.AutoReset = true;
            actionScheduler.timer.Start();
        }
        SchedulerDic[key] = actionScheduler;
    }

    /// <summary>
    /// 移除定时执行委托
    /// </summary>
    /// <param name="key"></param>
    public static void Remove(string key)
    {
        if (SchedulerDic.TryGetValue(key, out var scheduler))
        {
            if (scheduler.timer != null)
            {
                scheduler.timer.Stop();
                scheduler.timer.Dispose();
            }
            if (scheduler.timerUI != null)
            {
                scheduler.timerUI.Stop();
                scheduler.timerUI.Dispose();
            }
            scheduler.actions = null;
            SchedulerDic.Remove(key);
        }
    }

    /// <summary>
    /// 移除所有的定时器
    /// </summary>
    public static void Dispose()
    {
        foreach (var scheduler in SchedulerDic.Values)
        {
            if (scheduler.timer != null)
            {
                scheduler.timer.Stop();
                scheduler.timer.Dispose();
                scheduler.actions = null;
            }
            if (scheduler.timerUI != null)
            {
                scheduler.timerUI.Stop();
                scheduler.timerUI.Dispose();
                scheduler.actions = null;
            }
        }
        SchedulerDic.Clear();
    }

    public class ActionSchedulerInfo
    {
        public System.Timers.Timer timer { get; set; }
        public System.Windows.Forms.Timer timerUI { get; set; }
        public Action actions { get; set; }
    }
}

添加:

TimerScheduler.Add("Test", 2, false, () =>
{
    Console.WriteLine("这是一个定时器");
});

这里使用了一个 Lambda 表达式,你可以直接替换成一个无参数的方法。

移除:

TimerScheduler.Remove("Test");

移除对应的 key,就能停止和清除这个定时器了。

end

  • 11
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C# 中,你可以使用以下几种方法来实现定时器功能: 1. System.Timers.Timer:这是一个基于线程的定时器,可以在指定的时间间隔内重复执行指定的代码。你可以设置 Interval 属性来指定时间间隔,并通过 Elapsed 事件来处理计时器事件。 ```csharp using System; using System.Timers; public class TimerExample { private static Timer timer; public static void Main() { timer = new Timer(); timer.Interval = 1000; // 设置时间间隔为1秒 timer.Elapsed += TimerElapsed; // 绑定事件处理程序 timer.Enabled = true; // 启动计时器 Console.WriteLine("Press Enter to stop the timer."); Console.ReadLine(); timer.Enabled = false; // 停止计时器 } private static void TimerElapsed(object sender, ElapsedEventArgs e) { Console.WriteLine("Timer elapsed at {0}", e.SignalTime); } } ``` 2. System.Threading.Timer:这是一个基于线程池的定时器,也可以在指定的时间间隔内重复执行指定的代码。你可以使用 Change 方法来设置时间间隔,并通过 TimerCallback 委托来处理计时器事件。 ```csharp using System; using System.Threading; public class TimerExample { private static Timer timer; public static void Main() { TimerCallback callback = new TimerCallback(TimerElapsed); timer = new Timer(callback, null, 0, 1000); // 设置时间间隔为1秒 Console.WriteLine("Press Enter to stop the timer."); Console.ReadLine(); timer.Dispose(); // 停止计时器 } private static void TimerElapsed(object state) { Console.WriteLine("Timer elapsed at {0}", DateTime.Now); } } ``` 3. System.Threading.Tasks.Task.Delay:这是一种基于异步任务的延迟执行方法,可以在指定的时间间隔后执行指定的代码。 ```csharp using System; using System.Threading.Tasks; public class TimerExample { public static async Task Main() { Console.WriteLine("Press Enter to start the timer."); Console.ReadLine(); while (true) { Console.WriteLine("Timer elapsed at {0}", DateTime.Now); await Task.Delay(1000); // 设置时间间隔为1秒 } } } ``` 这些是在 C# 中实现定时器功能的几种常用方法。你可以根据自己的需求选择适合的方法来实现定时器功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

熊思宇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值