当前位置: 首页 > news >正文

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


http://www.mrgr.cn/news/11152.html

相关文章:

  • 0基础学习Python路径(27)sys模块
  • 大数据挖掘的步骤是怎样的呢?
  • 如何使用ChatGPT进行数据共享和处理
  • 对派生类指针使用C风格的强制类型转换为基类指针
  • 谷粒商城实战笔记-249-商城业务-消息队列-RabbitMQ工作流程
  • 新手入门:Python+Selenium自动化测试(爬虫),如何自动下载WebDriver!
  • 2025秋招大语言模型落地实践面试题
  • 小程序审核昵称敏感词问题修复方案
  • Python使用Tesseract OCR识别文字
  • 民宿管理平台系统
  • 小程序全局本地存储和读取数据
  • Facebook AI的应用前景:如何利用人工智能提升平台功能
  • matlab与VS混合编程以及错误解决
  • TMDOG的微服务之路_07——初入微服务,NestJS微服务快速入门
  • 回调与观察者模式区分
  • 《计算机操作系统》(第4版)第10章 多处理机操作系统 复习笔记
  • 【MySQL数据库管理问答题】第8章 维护稳定的系统
  • Jenkins发邮件功能如何配置以实现自动化?
  • 需方软件供应链安全保障要求及开源场景对照自评表(上)
  • Unity 编辑器-监听创建控件,prefab创建或添加组件的自动处理⭐