多线程计时器
多线程计时器比较强大,精确,而且可扩展性强;
只要在使用 Timer,就必须保留对它的引用。 对于任何托管对象(就是交给.NET自动释放资源的对象),如果没有对 Timer 的引用,计时器会被垃圾回收器回收。 即使 Timer 仍处在活动状态,也会被回收。
当不再需要计时器时,请使用 Dispose 方法释放计时器持有的资源。 请注意,回调可能发生在 Dispose() 方法的重载被调用之后,因为计时器是按线程池线程来安排回调执行的。 可使用 Dispose(WaitHandle) 方法重载进行等待,直到完成所有的回调。
由计时器执行的回调方法是可重入的,因为它是在 ThreadPool 线程上调用的。 在以下两种情况中,此回调可以同时在两个线程池线程上执行: 一、是计时器间隔小于执行此回调所需的时间; 二、是所有线程池线程都在使用,此回调被多次排队。
System.Threading.Timer 是一个简单的轻量计时器,它使用回调方法并由线程池线程提供服务。 不建议将其用于 Windows 窗体,因为其回调不在用户界面线程上进行。 System.Windows.Forms.Timer 是用于 Windows 窗体的更佳选择。 要获取基于服务器的计时器功能,可以考虑使用 System.Timers.Timer,它可以引发事件并具有其他功能。
单线程计时器:
1:System.Windows.Forms.Timer(Windows Forms Timer)
2:System.Windows.Threading.DispatcherTimer(WPF Timer)
像 System.Timers.Timer 一样,他们也提供了相同的成员(Interval,Tick,Start,Stop),但是他们内部的工作原理不同, WPF 和 Windows Forms 的计时器使用消息循环机制来取代线程池产生消息的机制。
这意味着 Tick 事件总是在创建 Timer 的那个线程上执行,同时也意味着如果上一个 Tick 消息还未被处理,即使时间超过了间隔时间,在消息循环中也只存在一个 Tick 消息。
下面是它们的优点:
单线程计时器比较安全,对于更新 Windows Forms Controls 或者 WPF 这种简单任务来说更方便。
你可以忘记线程安全。一个 Tick 事件在前一个 Tick 事件被处理完毕前不会被触发。你可以直接在 Tick 事件处理代码中更新控件,不需要调用 Control.Invoke 或 Dispatcher.Invoke。
在.NET Framework里面提供了三种Timer
① System.Windows.Forms.Timer
② System.Timers.Timer
③ System.Threading.Timer
现分述如下
一、System.Windows.Forms.Timer
1、基于 Windows 消息循环,用【事件方式】触发,在界面线程执行;是使用得比较多的 Timer,Timer Start之后定时(按设定的Interval)调用挂接在【Tick事件】上的 EventHandler。在这种 Timer 的 EventHandler 中可以直接获取和修改UI元素而不会出现问题,因为这种 Timer 实际上就是在【UI线程】自身上进行调用的。
2、它是一个基于 Form 的计时器。
3、创建之后,你可以使用 Interval 设置 Tick 之间的跨度,用委托(delegate)hook Tick事件。
4、调用 Start 和 Stop 方法,开始和停止。
5、完全基于UI线程,因此部分UI相关的操作会在这个计时器内进行。
6、长时间的UI操作可能导致部分 Tick 丢失。
7、Timer 用于以用户定义的事件间隔触发事件。Windows 计时器是为【单线程】环境设计的,其中UI 线程用于执行处理。它要求用户代码有一个可用的 UI 消息泵,而且总是在同一个线程中操作,或者将调用封送到另一个线程。
8、Windows 将这个定时器与调用线程关联(UI线程)。当定时器触发时,Windows 把一个定时器消息插入到线程消息队列中。调用线程执行一个消息泵提取消息,然后发送到回调方法中(这里的myTimer_Tick方法)。而这些都是单线程进行了,所以在执行回调方法时UI会假死。所以使用这个控件不宜执行【计算受限】或【IO受限】的代码,因为这样容易导致界面假死,而应该使用多线程调用的 Timer。另外要注意的是这个控件时间精度不高,精度限定为55 毫秒。
二、System.Timers.Timer
1、用的不是 Tick 事件,而是【Elapsed事件】。
2、和 System.Windows.Forms.Timer 一样,用 Start 和 Stop 方法。
3、AutoReset 属性决定计时器是不是要发起一次事件然后停止,还是进入开始/等待的循环;System.Windows.Forms.Timer 没有这个属性。
4、设置对于UI控件的同步对象(synchronizing object),对控件的UI线程发起事件。
三、System.Threading.Timer
1、用 Threading.Timer 时的方法,和前面就不太相同了,所有的参数全部在构造函数中进行了设置,而且可以设置启动时间。而且没有提供 Start 和 Stop方法来控制计时器。而且是以一种【回调方法】的方式实现,而不是通过事件来实现的。他们之间还是有区别的。
2、我们只有销毁掉对象来停止他。当你运行时,你会发现他和前面的 Timers.Timer 一样,是多线程的,主要表现在不会假死,调试运行报错。但让你奇怪的是,我们的代码竟然无法让她停止下来。调用了 Dispose 方法也没有用。问题在那?然后进行了测试,修改了间隔时间为100ms,200ms,500ms,1000ms,3000ms,4000ms。这几种情况。发现当间隔为 500ms 以上是基本马上就停止了。而间隔时间相对执行时间越短,继续执行的时间越长。这应该是在间隔时间小于执行时间时多个线程运行造成的。因为所有的线程不是同时停止的。间隔越短,线程越多,所以执行次数越多。
3、System.Threading.Timer 是一个简单的轻量计时器,它使用回调方法并由【线程池】线程提供服务。不建议将其用于 Windows 窗体,因为其回调不在用户界面线程上进行。