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.rhkb.cn/news/413134.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

线性表之数组

数组&#xff08;Array&#xff09;是 C/C 中最基础和重要的数据结构之一&#xff0c;它提供了一种有效存储和访问固定大小元素集合的方式。关于数组的定义和使用相信大家都已经熟练掌握&#xff0c;本文将着重为大家剖析数组的物理结构和逻辑结构。 1. 数组的物理结构 数组的…

大语言模型-GPT3-Language Models are Few-Shot Learners

一、背景信息&#xff1a; GPT3是于2020 年由OpenAI 发布的预训练语言模型。 GPT3在自然语言处理&#xff08;NLP&#xff09;任务中表现出色&#xff0c;可以生成连贯的文本、回答问题、进行对话等。 GPT3的网络架构继续沿用GPT1、GPT2的是多层Transformer Decoder改的结构。…

MySQL的安装配置以及可视化工具的安装

一、MySQL 的安装配置 1、找到官网 MySQL :: Download MySQL Installer (Archived Versions)https://downloads.mysql.com/archives/installer/ 2、下载 3、安装 接下来只需要一直 next 下去就好 此时我们的MySQL就安装完成了&#xff0c;有些人的电脑在点击完这个finish以后…

Linux内核6.12新特性:panic之后扫码显示故障信息

Linux 内核 6.12 版本即将引入一项有趣的功能——在内核Panic时显示一个可选的二维码。这一功能将允许用户通过扫描二维码直接访问内核Panic信息的日志&#xff0c;从而更容易地诊断问题所在。 这不是 Linux 第一次尝试使用二维码。早在2014年&#xff0c;就有过关于在内核Pani…

HarmonyOS(52) 使用安全控件SaveButton保存图片

SaveButton使用简介 前言SaveButton简介约束与限制 实现点击事件全部源码 参考资料&#xff1a; 前言 在HarmonyOS(50) 截图保存功能实现一文中简单介绍了截图保存功能&#xff0c;本篇博文介绍一个更简单的保存图片控件SaveButton. SaveButton简介 SaveButton允许用户通过点…

EasyCVR中的H.265技术:助力实现大规模高效流畅的视频监控应用

随着视频监控技术的不断发展和用户对视频质量要求的不断提高&#xff0c;高效能、低延迟的视频编码技术成为视频监控系统中的重要支撑。TSINGSEE青犀视频旗下的EasyCVR视频汇聚平台凭借其强大的视频处理能力和对H.265技术的支持&#xff0c;在视频监控系统中展现出显著的应用优…

运用Premiere自学视频剪辑,这些岗位你能胜任!

随着短视频的兴起和火热&#xff0c;短视频后期制作越来越受到人们的重视&#xff0c;甚至衍生出很多岗位的高薪工作。如大家所了解的&#xff0c;Adobe premiere正是一款视频后期剪辑和制作工具&#xff0c;其功能强大&#xff0c;应用也十分广泛&#xff0c;是从事后期工作者…

Mysql常见问题汇总【持续更新】

文章目录 Invalid default value for CREATE_TIME 或则 启动时 sql_mode 报错1130错误码&#xff0c;MySQL不能通过ip连接第一种命令方式图形化界面 mysql给用户授管理员权限mysql 新建用户时&#xff0c;主机名选择区别Mysql常用命令大全 Invalid default value for CREATE_T…

四大消息队列:Kafka、ActiveMQ、RabbitMQ、RocketMQ对比

四大消息队列&#xff1a;Kafka、ActiveMQ、RabbitMQ、RocketMQ对比 1. 社区活跃度2. 持久化消息3. 技术实现4. 高并发性能5. RabbitMQ与Kafka对比 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在软件开发中&#xff0c;消息队列&#xf…

基础算法(1)——双指针

1. 概念 常见的双指针有两种形式&#xff0c;一种是对撞指针&#xff0c;一种是快慢指针 1.1 对撞指针 一般用于顺序结构中&#xff0c;也称为左右指针 对撞指针从两端向中间移动&#xff0c;一个指针从最左端开始&#xff0c;另一个从最右端开始&#xff0c;逐渐往中间逼近…

.net dataexcel winform控件 更新 日志

增加 列宽度调整时动态显示列象素大小 更改列的宽度可以使用 column.Width属性进行修改

【持续更新】Mχ Plaayer Pro 1.86.0安卓知名播放器最新免费高级修改版

Mχ Plaayer Pro MOD 版本免费 APK&#xff0c;专为安卓手机和平板打造。这是一款功能强大的视频播放器&#xff0c;具备先进的硬件加速技术和字幕支持功能。 • 硬件加速 - 新增 HW 解码器帮助更多视频格式实现硬件加速。 • 多核心解码 - Mχ Plaayer 是首款支持多核心解码的…

基于STM32的RFID高速收费系统(论文+源码+实物)

1系统方案设计 本文基于STM32的RFID高速收费系统&#xff0c;其可以实现小车和货车两种车型收费&#xff0c;当车辆超过了规定的重量后&#xff0c;出现声光报警提示&#xff0c;并且启动杆不会抬起&#xff0c;只有当车辆重量低于设置值时&#xff0c;启动杆才会自动抬起&…

【Linux】在 bash shell 环境下,当一命令正在执行时,按下 control-Z 会?

目录 题目分析答案 题目 分析 ctrl-c&#xff1a; 发送 SIGINT 信号给前台进程组中的所有进程。常用于终止正在运行的程序&#xff1b;ctrl-z&#xff1a; 发送 SIGTSTP信号给前台进程组中的所有进程&#xff0c;常用于挂起一个进程&#xff1b;ctrl-d&#xff1a; 不是发送信…

揭秘排行榜系统:如何在高并发场景下实现高效更新!

大家好,我是你们的技术分享伙伴小米!今天我们来聊聊一个非常有趣的话题——如何设计一个排行榜。在这个互联网时代,无论是游戏、学习平台,还是各种社交应用,排行榜都是用户互动和竞争的核心功能之一。而如何设计一个高效、实时更新的排行榜,是一个充满挑战性的问题。今天…

win11,vscode上用docker环境跑项目

1.首先用dockerfile创建docker镜像 以下是dockerfile文件的内容&#xff1a; FROM pytorch/pytorch:1.11.0-cuda11.3-cudnn8-devel LABEL Service"SparseInstanceActivation"ENV TZEurope/Moscow ENV DETECTRON_TAGv0.6 ARG DEBIAN_FRONTENDnoninteractiveRUN apt-…

vim常用快捷键问答

vim的光标位置操作快捷键有哪些&#xff1f;怎样记忆它们&#xff1f; 在 Vim 中&#xff0c;光标位置的操作快捷键非常重要&#xff0c;可以帮助你更高效地编辑文本。下面是一些常用的光标位置操作快捷键&#xff1a; 基本移动 h&#xff1a;光标左移一个字符j&#xff1a;光…

使用安信可Ai-WB2-12F开启wifi与手机通信TCP-IP(AT指令)

当时在做两个单片机之间无线通信&#xff0c;或者单片机与手机无线通信&#xff0c;就像找一个蓝牙和wifi双模的无线模块&#xff0c;一开始看ESP8684&#xff08;ESP32-C2&#xff09;这个芯片模组是有wifi和蓝牙的&#xff0c;买回来后才发现他不可以在程序运行中更换蓝牙或者…

主流AI绘画工具-StableDiffusion本地部署方法(mac电脑版本)

Stable Diffusion是一款强大的AI生成图像模型&#xff0c;它可以基于文本描述生成高质量的图像。对于想要在本地运行此模型的用户来说&#xff0c;使用Mac电脑部署Stable Diffusion是一个非常吸引人的选择&#xff0c;特别是对于M1或M2芯片的用户。本文将详细介绍如何在Mac上本…

视频化时代,用好AIGC产品赋能企业培训打造增效降本“最佳实践”

根据IBM的数据&#xff0c;85%的中国企业正在加速投资AI领域&#xff0c;其中超过63%的企业已积极采用生成式AI。德勤的调研进一步显示&#xff0c;近80%的全球受访企业高管认为&#xff0c;生成式AI的兴起与发展将在3年内推动组织和行业发生实质性变革&#xff0c;这也就意味着…