C# System.Threading.Timer 延迟执行以及定时器

有时候我们需要实现延迟执行,或者是定时执行,这个时候可以使用System.Threading.Timer

Timer4个参数

TimerCallback callback:执行的函数,需要传入一个object类型的参数

object state:callback传入的参数的值,如果没有的话写成null

int dueTime:延迟执行的时间,即几毫秒后执行操作,单位毫秒

int period:定时执行的时间,即每隔几毫秒后执行一次操作,单位毫秒

如果要实现延迟执行的效果,那就传入dueTime,并且把period设置成-1或者Timeout.Infinite

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/// <summary>
        /// 延迟3秒后执行
        /// </summary>
        static void Test1() {
            Console.WriteLine(DateTime.Now + " 开始...");
            Timer timer = new Timer(args => {
                try {
                    Console.WriteLine(DateTime.Now + " 执行操作");
                } catch (Exception) {
 
                }
            }, null, 3000, Timeout.Infinite);
            Console.WriteLine(DateTime.Now + " 等待中...");
        }

  如果要实现定时执行的效果,就可以传入period数值,dueTime如果传入0的话,定时器就会在启动后立刻执行一次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/// <summary>
        /// 立刻执行一次后每隔2秒执行一次
        /// </summary>
        static void Test2() {
            Console.WriteLine(DateTime.Now + " 开始...");
            Timer timer = new Timer((p) => {
                try {
                    Console.WriteLine(DateTime.Now + " 执行操作");
                } catch (Exception) {
 
                }
            }, null, 0, 2000);
            Console.WriteLine(DateTime.Now + " 等待中...");
        }

  定时执行很爽,但是如果业务代码异常了或者是阻塞了,Test2依然会继续循环调用,不断的申请资源,一个处理不好,就很容易导致系统崩溃,那么有咩有什么办法能让Timer业务不执行完就不开始下一个任务呢,答案是可以的,就是利用Timer的Change函数来每次延迟执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/// <summary>
        /// 每次延迟2秒执行,执行完毕后再延迟2秒
        /// </summary>
        static void Test3() {
            Console.WriteLine(DateTime.Now + " 开始...");
            Timer timer = null;
            timer = new Timer((arg) => {
                try {
                    Console.WriteLine(DateTime.Now + " 延迟执行到了");
                    Thread.Sleep(3000); //模拟3秒的操作耗时
                    Console.WriteLine(DateTime.Now + " 执行操作");
                } catch (Exception) {
 
                } finally {
                    timer.Change(2000, Timeout.Infinite);  //执行完3秒的操作后,再延迟2秒后执行
                }
            }, null, 2000, Timeout.Infinite);  //第一次延迟2秒执行
        }

还有就是这个Timer不要像我这样在方法中当作局部变量使用,因为资源紧张的时候GC有可能会把它给回收了,
Test1和Test3延迟执行不存在这个问题,但是Test2是循环执行就会出现这个问题,如果资源紧张,可能循环走着走着就没了
所以用的时候一定要避免在方法中作为局部变量用,最好是把创建的Timer对象指向一个非局部变量

 

posted @   WmW  阅读(3415)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示