c# 线程定时器 System.Threading.Timer的使用

 更新时间:2023年02月06日 11:09:28   作者:驰愿  
本文主要介绍了c# 线程定时器 System.Threading.Timer的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

System.Threading.Timer 是由线程池调用的。

所有的Timer对象只使用了一个线程来管理。这个线程知道下一个Timer对象在什么时候到期。下一个Timer对象到期时,线程就会唤醒,在内部调用ThreadPool 的 QueueUserWorkItem,将一个工作项添加到线程池队列中,使你的回调方法得到调用。如果回调方法的执行时间很长,计时器可能(在上个回调还没有完成的时候)再次触发。这可能造成多个线程池线程同时执行你的回调方法。

参数

  • callback : 一个Object 类型参数的委托,周期调用的函数。
  • state: callback 委托调用时的参数。
  • dueTime: 定时器延时多久开始调用。单位 毫秒
  • period: 定时器每隔多久调用一次。单位 毫秒

不能使用局部变量来创建指向一个线程定时器。因为局部变量会被GC回收,导致定时器失效。
比如下面的例子:

		static void Main(string[] args) {

            Run();

            //为了加快GC垃圾回收,不停的创建对象
            for (int i = 0; i < 10000; i++) {
                cc tmp = new cc();
                Thread.Sleep(10);
            }

            Console.ReadKey();

        }

        static int id;

        static void Run() {
            Timer timer = new Timer(DoTime, null, 500, 500);
        }

        static void DoTime(object obj) {
            Console.WriteLine(id++);
        }

        class cc{ 
            public int[] a = new int[1000];
            }

在这里插入图片描述

定时器执行4次后停止了。定时器什么时候停止取决于GC什么时候回收。如果一直没有GC的回收,那么将会一直执行下去。比如把上方创建 cc 对象的代码删除。定时器将会一直执行。

可以在Main方法中使局部变量 或者 使用全局变量来存放Timer 对象 避免 clr 把Timer 回收。

比如改成这样

        static Timer timer;

        static void Main(string[] args) {

            timer =  new Timer(DoTime, null, 500, 500);

            //为了加开GC垃圾回收,不停的创建对象
            for (int i = 0; i < 10000; i++) {
                cc tmp = new cc();
                Thread.Sleep(10);
            }

            Console.ReadKey();

        }

        static int id;

        static void DoTime(object obj) {
            Console.WriteLine(id++);
        }

如果回调方法的执行时间很长,计时器可能(在上个回调还没有完成的时候)再次触发。这可能造成多个线程池线程同时执行你的回调方法。

	    static Timer timer1;

        static void Main(string[] args) {

            timer1 = new Timer(DoTime, 1, 500, 500);


            Console.ReadKey();

        }

        static int id;

        static void DoTime(object obj) {
            int idx = id ++;
            Console.WriteLine("处理开始:" + idx + "," + Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(1200);
            Console.WriteLine("处理完毕:" + idx + "," + Thread.CurrentThread.ManagedThreadId);
        }

在这里插入图片描述

定时器第一次任务还没执行完毕,第二次,第三次回调就开始了。多个线程同时并发 DoTime 方法

解决方法

period 使用 Timeout.Infinite。这个参数将导致DoTime 只处理一次。
在回调方法中使用 Change方法来修改 dueTime,period 参数。period 继续使用 Timeout.Infinite. 使用这个方法要注意如果timer 在被Dispose了,使用Change 将会引发异常。
比如

 		static Timer timer1;

        static void Main(string[] args) {

            timer1 = new Timer(DoTime, 1, 0, Timeout.Infinite);

            Console.ReadKey();

        }

        static int id;

        static void DoTime(object obj) {
            int idx = id ++;
            Console.WriteLine("处理开始:" + idx + "," + Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(1200);
            Console.WriteLine("处理完毕:" + idx + "," + Thread.CurrentThread.ManagedThreadId);
            timer1.Change(500,Timeout.Infinite);
        }

在这里插入图片描述

使用Disponse停止定时器
如果Timer 不会再使用 则可以 使用 Dispose 方法来停止定时器。
如果定时器运行到中途。使用Dispose方法后,callback还是会执行完一个完整的生命周期,不会中途停止。并且Dispose方法不会等待 callback的这次调用完成。只是定时器下次不再调用 callback。

使用Change停止定时器
把 dueTime 参数置为-1就可以停止定时器。同样的,它不会中断在运行中的callback,只是下一次不再回调。 这个方法停止的定时器 还可以使用Change 再次利用定时器。

到此这篇关于c# 线程定时器 System.Threading.Timer的使用的文章就介绍到这了,更多相关c# 线程定时器 System.Threading.Timer内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C# Console.WriteLine()用法案例详解

    C# Console.WriteLine()用法案例详解

    这篇文章主要介绍了C# Console.WriteLine()用法案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • C#实现的文件压缩和解压缩类

    C#实现的文件压缩和解压缩类

    这篇文章主要介绍了C#实现的文件压缩和解压缩类,实例分析了C#针对文件压缩与解压缩的常用技巧,非常具有实用价值,需要的朋友可以参考下
    2015-03-03
  • C#实现图形位置组合转换的方法

    C#实现图形位置组合转换的方法

    这篇文章主要介绍了C#实现图形位置组合转换的方法,涉及C#使用Matrix操作图形的相关技巧,需要的朋友可以参考下
    2015-06-06
  • C# dataset存放多张表的实例

    C# dataset存放多张表的实例

    这篇文章主要介绍了C# dataset存放多张表的实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • C#中对集合排序的三种方式

    C#中对集合排序的三种方式

    这篇文章介绍了C#中对集合排序的三种方式,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • C#编写控制台程序纸牌游戏

    C#编写控制台程序纸牌游戏

    这篇文章主要为大家详细介绍了C#编写控制台程序纸牌游戏,适合C#初学者,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-08-08
  • 深入c# Func委托的详解

    深入c# Func委托的详解

    本篇文章是对c#中的Func委托进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • PC蓝牙通信C#代码实现

    PC蓝牙通信C#代码实现

    这篇文章主要为大家详细介绍了PC蓝牙通信C#代码实现,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-09-09
  • C#启动进程的几种常用方法

    C#启动进程的几种常用方法

    这篇文章主要介绍了C#启动进程的几种常用方法,实例分析了C#对系统进行的相关操作技巧,需要的朋友可以参考下
    2015-05-05
  • c#使用htmlagilitypack解析html格式字符串

    c#使用htmlagilitypack解析html格式字符串

    这篇文章主要介绍了c#使用htmlagilitypack解析html格式字符串的示例,需要的朋友可以参考下
    2014-03-03

最新评论