C# System.Threading.Timer 与 System.Timers.Timer 的一点点区别

news/2025/1/9 21:25:00/文章来源:https://www.cnblogs.com/pencilstart/p/18662925

先说一下结论:差不多。

我目前明显感受到的唯一的差别是,Timers.Timer 的启动时,先要等一个 interval 时间,才触发 Timers.Timer.ElapsedEventHandler。

而Threading.Timer,可以做到先触发,再等一个 interval 时间,再触发下一次。

这个给个简单例子与结果:

using System;
using System.Diagnostics;
using System.Threading;namespace ConsoleApplication1
{class UnSafeTimer{static int i = 0;static System.Threading.Timer timer;static object mylock = new object();static int sleep;static bool flag;public static Stopwatch sw = new Stopwatch();static void Excute(object obj){Console.WriteLine("Excute() current thread id = {0}/{1}", System.Threading.Thread.CurrentThread.ManagedThreadId,AppDomain.GetCurrentThreadId());Thread.CurrentThread.IsBackground = false;int c;lock (mylock){i++;c = i;}if (c == 80){timer.Dispose();//执行Dispose后Timer就不会再申请新的线程了,但是还是会给Timmer已经激发的事件申请线程
                sw.Stop();}if (c < 80)Console.WriteLine("Now:" + c.ToString());else{Console.WriteLine("Now:" + c.ToString() + "-----------Timer已经Dispose耗时:" + sw.ElapsedMilliseconds.ToString() + "毫秒");}if (flag){Thread.Sleep(sleep);//模拟花时间的代码
            }else{if (i <= 80)Thread.Sleep(sleep);//前80次模拟花时间的代码
            }}public static void Init(int p_sleep, bool p_flag){Console.WriteLine("Init() current thread id = {0}/{1}", System.Threading.Thread.CurrentThread.ManagedThreadId,AppDomain.GetCurrentThreadId());sleep = p_sleep;flag = p_flag;timer = new System.Threading.Timer(Excute, null, 0, 10);}}class SafeTimer{static int i = 0;static System.Threading.Timer timer;static bool flag = true;static object mylock = new object();static void Excute(object obj){Thread.CurrentThread.IsBackground = false;lock (mylock){if (!flag){return;}i++;if (i == 80){timer.Dispose();flag = false;}Console.WriteLine("Now:" + i.ToString());}Thread.Sleep(1000);//模拟花时间的代码
        }public static void Init(){timer = new System.Threading.Timer(Excute, null, 0, 10);}}class Program{static void test1(){ThreadPool.SetMinThreads(500, 10);Console.Write("是否使用安全方法(Y/N)?");string key = Console.ReadLine();if (key.ToLower() == "y")SafeTimer.Init();else{Console.Write("请输入Timmer响应事件的等待时间(毫秒):");//这个时间直接决定了前80个任务的执行时间,因为等待时间越短,每个任务就可以越快执行完,那么80个任务中就有越多的任务可以用到前面任务执行完后释放掉的线程,也就有越多的任务不必去线程池申请新的线程避免多等待半秒钟的申请时间string sleep = Console.ReadLine();Console.Write("申请了80个线程后Timer剩余激发的线程请求是否需要等待时间(Y/N)?");//这里可以发现选Y或者N只要等待时间不变,最终Timer激发线程的次数都相近,说明Timer的确在执行80次的Dispose后就不再激发新的线程了key = Console.ReadLine();bool flag = false;if (key.ToLower() == "y"){flag = true;}UnSafeTimer.sw.Start();UnSafeTimer.Init(Convert.ToInt32(sleep), flag);}Console.WriteLine("Press any key to exit.");Console.ReadLine();}static int onTimerCount = 0;//static object locker = new object();static void test2(){onTimerCount = 0;ThreadPool.SetMinThreads(1, 10);ThreadPool.SetMaxThreads(5, 10);System.Timers.Timer t = new System.Timers.Timer();t.Interval = 500;t.AutoReset = true;t.Elapsed += OnTimedEvent;Console.WriteLine("[{2}] test2() current thread id = {0}/{1}", System.Threading.Thread.CurrentThread.ManagedThreadId, AppDomain.GetCurrentThreadId(), DateTime.Now.ToString("HH:mm:ss.fff"));t.Start();Thread.Sleep(5000);t.Stop();Console.WriteLine("Press any key to exit.");Console.ReadLine();}private static void OnTimedEvent(object sender, System.Timers.ElapsedEventArgs e){DateTime dt = DateTime.Now;++onTimerCount;int tmpcount = onTimerCount;Console.WriteLine("[{3}] OnTimedEvent({2}) BEGIN: current thread id = {0}/{1}", System.Threading.Thread.CurrentThread.ManagedThreadId, AppDomain.GetCurrentThreadId(), tmpcount, dt.ToString("HH:mm:ss.fff"));Thread.Sleep(3100);Console.WriteLine("[{3}] OnTimedEvent({2}) END: current thread id = {0}/{1}", System.Threading.Thread.CurrentThread.ManagedThreadId, AppDomain.GetCurrentThreadId(), tmpcount, DateTime.Now.ToString("HH:mm:ss.fff"));}static void test3(){onTimerCount = 0;ThreadPool.SetMinThreads(1, 10);ThreadPool.SetMaxThreads(5, 10);System.Threading.Timer t = new System.Threading.Timer(TimedCB);Console.WriteLine("[{2}] test3() current thread id = {0}/{1}", System.Threading.Thread.CurrentThread.ManagedThreadId, AppDomain.GetCurrentThreadId(), DateTime.Now.ToString("HH:mm:ss.fff"));t.Change(0, 500);//System.Threading.Timer t = new System.Threading.Timer(TimedCB, null, 0, 500);
Thread.Sleep(5000);t.Change(-1, Timeout.Infinite);Console.WriteLine("Press any key to exit.");Console.ReadLine();}private static void TimedCB(object state){DateTime dt = DateTime.Now;++onTimerCount;int tmpcount = onTimerCount;Console.WriteLine("[{3}] TimedCB({2}) BEGIN: current thread id = {0}/{1}", System.Threading.Thread.CurrentThread.ManagedThreadId, AppDomain.GetCurrentThreadId(), tmpcount, dt.ToString("HH:mm:ss.fff"));Thread.Sleep(3100);Console.WriteLine("[{3}] TimedCB({2}) END: current thread id = {0}/{1}", System.Threading.Thread.CurrentThread.ManagedThreadId, AppDomain.GetCurrentThreadId(), tmpcount, DateTime.Now.ToString("HH:mm:ss.fff"));}static void Main(string[] args){//test1();
test2();test3();}}
}

运行结果:

[21:15:06.807] test2() current thread id = 1/15444
[21:15:07.328] OnTimedEvent(1) BEGIN: current thread id = 4/27956
[21:15:07.827] OnTimedEvent(2) BEGIN: current thread id = 5/2664
[21:15:08.341] OnTimedEvent(3) BEGIN: current thread id = 6/29164
[21:15:08.853] OnTimedEvent(4) BEGIN: current thread id = 7/12292
[21:15:09.365] OnTimedEvent(5) BEGIN: current thread id = 8/28156
[21:15:10.443] OnTimedEvent(1) END: current thread id = 4/27956
[21:15:10.938] OnTimedEvent(2) END: current thread id = 5/2664
[21:15:10.938] OnTimedEvent(6) BEGIN: current thread id = 5/2664
[21:15:11.446] OnTimedEvent(3) END: current thread id = 6/29164
[21:15:11.446] OnTimedEvent(7) BEGIN: current thread id = 6/29164
Press any key to exit.
[21:15:11.959] OnTimedEvent(4) END: current thread id = 7/12292
[21:15:12.472] OnTimedEvent(5) END: current thread id = 8/28156
[21:15:14.054] OnTimedEvent(6) END: current thread id = 5/2664
[21:15:14.548] OnTimedEvent(7) END: current thread id = 6/29164[21:15:20.428] test3() current thread id = 1/15444
[21:15:20.429] TimedCB(1) BEGIN: current thread id = 5/2664
[21:15:20.932] TimedCB(2) BEGIN: current thread id = 6/29164
[21:15:21.442] TimedCB(3) BEGIN: current thread id = 7/12292
[21:15:21.952] TimedCB(4) BEGIN: current thread id = 8/28156
[21:15:22.965] TimedCB(5) BEGIN: current thread id = 4/27956
[21:15:23.536] TimedCB(1) END: current thread id = 5/2664
[21:15:23.536] TimedCB(6) BEGIN: current thread id = 5/2664
[21:15:24.034] TimedCB(2) END: current thread id = 6/29164
[21:15:24.050] TimedCB(7) BEGIN: current thread id = 6/29164
[21:15:24.557] TimedCB(3) END: current thread id = 7/12292
[21:15:24.557] TimedCB(8) BEGIN: current thread id = 7/12292
[21:15:25.054] TimedCB(4) END: current thread id = 8/28156
[21:15:25.069] TimedCB(9) BEGIN: current thread id = 8/28156
Press any key to exit.
[21:15:26.069] TimedCB(5) END: current thread id = 4/27956
[21:15:26.641] TimedCB(6) END: current thread id = 5/2664
[21:15:27.156] TimedCB(7) END: current thread id = 6/29164
[21:15:27.667] TimedCB(8) END: current thread id = 7/12292
[21:15:28.178] TimedCB(9) END: current thread id = 8/28156

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/866751.html

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

相关文章

主机与虚拟机互ping不通的解决办法

一、主机ping不通虚拟机,但虚拟机可以ping主机 解决办法:二、虚拟机ping不通主机,但主机可以ping虚拟机 解决办法: 这里说的第一点我不知道,我是虚拟机可以ping通百度,之前虚拟机有过相关配置 我这里主要是win11电脑网络连接这里开启防火墙下面简单的说明下Vmware的网络连…

Win32汇编学习笔记09.SEH和反调试

Win32汇编学习笔记09.SEH和反调试-C/C++基础-断点社区-专业的老牌游戏安全技术交流社区 - BpSend.net SEH - structed exception handler 结构化异常处理 跟筛选一样都是用来处理异常的,但不同的是 筛选器是整个进程最终处理异常的函数,但无法做到比较精细的去处理异常(例如处理…

【Windows攻防】Windows注册表 IFEO注入

介绍 IFEO 注入攻击是一种基于注册表的攻击技术,几乎可以保证以登录用户甚至管理员/系统用户的身份执行代码。在任何你可以想象的用例中,如果你想要将你的有效载荷绑定到 Windows 平台上二进制文件的“启动”,IFEO(图像文件执行选项)可能是你最好的选择。这是一种开发人员…

[Java] 计算Java对象大小

序在Java应用程序的性能优化场景中,时常需要考虑Java对象的大小,以便评估后,进一步提出优化方案:占用内存的大小。(比如 本地内存) 对象数据在网络传输中占用的网络带宽 对象数据在存储时占用的磁盘空间 ...概述 对象大小如何计算对象大小包括俩部分的内容,对象头和对象…

并行前缀(Parallel Prefix)加法器

并行前缀(Parallel Prefix)加法器 并行前缀加法器的基本介绍 二进制加法器是目前数字计算单元中的重要模块,基础的加法器架构包括行波进位加法器(Ripple Carry Adder),超前进位加法器(Carry Look-Ahead Adder),进位选择加法器(Carry Select Adder)等。加法器的进位传…

科技风?写实风?教你设置多风格三维地图

概述 三维地图通过高度、深度、立体感等表现形式,能够真实还原地形地貌、城市建筑和空间结构。相比二维地图,它能够更清晰地展示复杂的地理数据,帮助用户快速理解空间关系,如地形起伏、建筑高度等。在实际应用中,我们可以将不同风格的三维地图作为项目的主体元素进行展示,…

【模拟电子技术】03-PN与二极管的特性

【模拟电子技术】03-PN与二极管的特性上节中有提到对PN结施加反向电压时,会使得PN结所形成的势垒增加,阻止多子到另一边。在掺杂浓度比较低的时候,外加电场加强,中间的耗尽层会加长,变成了一个粒子加速器,自由电子进去后不断加速。直到某一电场强度时,粒子加速足够大的时…

NocoBase 本周更新汇总:支持大规模数据量的导入和导出

本周更新包括:支持大规模数据量的导入和导出等。汇总一周产品更新日志,最新发布可以前往我们的博客查看。 NocoBase 目前更新包括的版本更新包括三个分支:main ,next和 develop。main :截止目前最稳定的版本,推荐安装此版本。 next:包含即将发布的新功能,经过初步测试的…

MSSQL:DBLINK连接oracle 19

无法为该请求检索数据。(Microsoft.SqlServer.Management.Sdk.Sfc)其他信息:执行Transact-SQL语句或批处理时发生了异常。(Microsoft.SqlServer.ConnectionInfo)在与SQL Server 建立连接时出现与网络相关的特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正…

五款强大报表软件助力企业提升数据分析效率

本文将为大家介绍五款功能强大的报表软件,包括山海鲸报表、JReport、Power BI、Zoho Analytics 和 SAP Crystal Reports。这些工具各具特色,能够帮助企业快速生成数据报表并进行深度分析。无论是数据可视化、报表定制、自动化生成还是与其他系统的集成,它们都能为企业的决策…

Linq中的设置操作 (C#):Distinct 和 DistinctBy、Except 和 ExceptBy、Intersect 和 IntersectBy、Union 和 UnionBy

LINQ 中的集运算是指根据相同或单独集合中是否存在等效元素来生成结果集的查询运算。 注:这些示例使用 System.Collections.Generic.IEnumerable<T> 数据源。 基于 System.Linq.IQueryProvider 的数据源使用 System.Linq.IQueryable<T> 数据源和表达式树。 表达式…

2025多校冲刺省选模拟赛3

过于困难,直接放弃2025多校冲刺省选模拟赛3\(T1\) A. 等差 \(100pts/100pts\)考虑哈希,每 \(k\) 个作为一组与上一组统一计算。取 \(Base>\) 值域时用高精度来存储并判断的正确性显然。观察到可行的最小的 \(k\) 单调不降,不妨直接枚举答案。暴力实现时间复杂度为 \(O(n…