这几天由于项目中设计到用定时器实时调用webserver获取数据,开始想到用线程,但是由于webservice返回太慢,上一个线程无法结束,下个线程无法开启。出现假死的情况。所以考虑使用定时器,这样每次不管webserver调用结果是否返回,直接执行定时启动下一个任务。达到实时刷新的目的.本文通过CLR via C#(第3版)整理学习出来。
(一)定时器总结:
(1)System.Threading的Timer类:要在一个线程池上执行定时的(周期性发生的)后台任务时,它是最好的定时器
(2)System.Windows.Forms的Timer类:构造这个类的一个实例,相当于告诉Windows将一个定时器和调用线程关联(参见Win32_SetTimer)。这个定时器出发时,Windows将一条计时器消息(WM_TIMER)注入线程的消息队列。线程必须将执行消息泵提出这些消息,并把它们派遣给想要的回调方法。注意,这里的工作都有一个线程完成---设置计算器的线程保证就是执行回调方法的线程,这还意味着你的计时器不会由多个线层并发执行。
(3)System.Windows.Threading的DispatcherTimer类:这个是System.Windows.Forms的Timer类在在silverlight 和WPF中的等价物。
(4)System.Timers的Timer类:基本上是System.Threading的Timer类的包装。这个类应该删除。除非真的想在设计平面中添加一个计时器。
(二)代码示例:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Diagnostics; namespace TimerDemo { /// <summary> /// 定时器总结: /// (1)System.Threading的Timer类:要在一个线程池上执行定时的(周期性发生的)后台任务是时,它是最好的定时器 /// (2)System.Windows.Forms的Timer类:Windows将一个定时器和死奥用线程关联。计时器消息注入线程队列。执行消息泵提出这些消息 /// (3)System.Windows.Threading的Timer类:这个是System.Windows.Forms的Timer类在在silverlight 和WPF中的等价物 /// (4)System.Timers的Timer类:基本上是System.Threading的Timer类的包装。这个类应该删除。除非真的想在设计平面中添加一个计时器。 /// </summary> class Program { static void Main(string[] args) { //TestDemo1(); TestDemo2(); Console.ReadLine(); } #region TestDemo1 public static int i = 1; private static void TimerCallback(object o) { Debug.WriteLine("调用第{0}次",i); Console.WriteLine("In TimerCallback: "+DateTime.Now); GC.Collect(); i++; } private static void TestDemo1() { Timer t = new Timer(TimerCallback, null, 0, 2000); Console.ReadLine(); //由于ReadLine之后引用t(会被被优化掉) //因为JIT编译器是一个优化的编译器,将局部变量或参数设为null。 //换言之JIT编译器会将t=null整行代码删除(优化掉) //所以回调放在Debug情况下会方法会被调用多次,而在Release下只调用一次 //t = null; //t.Dispose(); } #endregion #region //构造一个Timer类的实例相当于告诉线程池:在将来某个时间(具体由你定)回调你的一个方法 //在内部,线程池为所有的Timer对象只是用一个线程。这个线程知道下一个Timer对象什么时候到期(计时器还有多久触发) //下一个Timer对象到期时,在内部调用ThreadPool的QueueUserWorkItem.将一个工作项添加到线程池的队列中,使你的回调方法得到回到。 private static Timer s_Timer; private static void TestDemo2() { Console.WriteLine("Main thread: starting a timer"); using(s_Timer=new Timer(ComputeBoundOP,5,0,Timeout.Infinite)) { Console.WriteLine("Main thread: Doing other work here..."); Thread.Sleep(1000); }//现在用Dispose取消计时器 } private static void ComputeBoundOP(object state) { //这个方法由一个线程池线程执行 Console.WriteLine("In ComputerBondOp:state={0}",state); //模拟其他工作 Thread.Sleep(1000); //让Timer在2秒后再调用这个方法 s_Timer.Change(2000, Timeout.Infinite); //这个方法返回时,线程回归池中,等待下一个工作项 } #endregion } }