深入浅出多线程系列之七:4种定时器

60 篇文章 2 订阅

在Framework中存在着4种定时器:其中分为两类,

多线程计时器

1:System.Threading.Timer

2:System.Timers.Timer

 

特殊目的的单线程计时器:

1:System.Windows.Forms.Timer(Windows Forms Timer)

2:System.Windows.Threading.DispatcherTimer(WPF timer);

 

多线程计时器比较强大,精确,而且可扩展性强;

单线程计时器比较安全,对于更新 Windows Forms controls或者WPF这种简单任务来说更方便。

 

System.Threading.Timer是最简单的多线程计时器。在下面的例子中,定时器在5秒后开始定时1秒的调用Tick方法。

复制代码
       public  static  void Main ()
        {
             // 5秒后开始运行,接着每隔1秒的调用Tick方法
            Timer tmr =  new Timer(Tick,  " tick... "50001000);
            Console.ReadLine();
            tmr.Dispose();
        }
         static  void Tick( object data)
        {
            Console.WriteLine(data);
        }
复制代码

 

.net framework提供的另一个计时器System.Timers.Timer.简单的对System.Threading.Timer进行了包装。增加了下面几个特性。

  1. 实现了Component,所以可以在设计器显示。
  2. 代替Change方法的一个Interval属性
  3. 代替callback委托的一个Elapsed事件
  4. 启动和停止timer的Enabled属性,默认是false。
  5. 为了避免Enabled造成混乱,提供了Start和Stop方法。
  6. 是否在每次指定的间隔结束时引发Elapsed时间,还是仅间隔第一次结束后运行的AutoReset属性。
  7. 在WPF或Windows Forms中安全的调用方法的SynchronizingObject对象。
复制代码
public  static  void MainThread()
        {
            Timer tmr =  new Timer();
            tmr.Interval =  500;
            tmr.Elapsed +=  new ElapsedEventHandler(tmr_Elapsed);
            tmr.Start();
            Console.ReadLine();
            tmr.Stop();
            Console.ReadLine();
            tmr.Start();
            Console.ReadLine();
            tmr.Dispose();
        }

         static  void tmr_Elapsed( object sender, ElapsedEventArgs e)
        {
            Console.WriteLine( " Tick... ");
        }
复制代码

 

 

单线程计时器:

1:System.Windows.Forms.Timer(Windows Forms Timer)

2:System.Windows.Threading.DispatcherTimer(WPF timer);

单线程计时器是被设计成属于他们执行环境的计时器,如果你在一个Windows服务应用程序中使用Windows Forms的Timer,timer 事件并不会被触发,只有在对应的环境下才会被触发。

 

 

像System.Timers.Timer一样,他们也提供了相同的成员(Interval,Tick,Start,Stop),但是他们内部的工作原理不同,

WPFWindows Forms的计时器使用消息循环机制来取代线程池产生消息的机制。

这意味着Tick事件总是在创建timer的那个线程上执行,同时也意味着如果上一个Tick消息还未被处理,即使时间超过了间隔时间,在消息循环中也只存在一个Tick消息。

 

下面是它们的优点:

  1. 你可以忘记线程安全。
  2. 一个Tick事件在前一个Tick事件被处理完毕前不会被触发。
  3. 你可以直接在Tick事件处理代码中更新控件,不需要调用Control.Invoke或Dispatcher.Invoke.

看下在Winform中使用单线程定时器的效果:

复制代码
       // 基于Windows消息循环的单线程计时器
         private System.Windows.Forms.Timer timer =  new Timer() { };

         public Form1()
        {
            InitializeComponent();

            timer.Tick +=  new EventHandler(timer_Tick);
            timer.Enabled =  true;
        }

         void timer_Tick( object sender, EventArgs e)
        {
             // 模拟的做一些耗时的操作
            System.Threading.Thread.Sleep( 2000);
        }
复制代码

 

如果运行上面的代码,会发现UI界面响应速度很慢,

原理上面已经介绍了:单线程计时器基于Windows消息循环,应用程序会同步的处理计时器的消息。

解决这个问题的方法是使用多线程计时器:只要修改代码使用多线程计时器即可:

 

复制代码
        // 使用多线程计时器
         private System.Timers.Timer timer =  new System.Timers.Timer();

         public Form1()
        {
            InitializeComponent();

            timer.Elapsed +=  new System.Timers.ElapsedEventHandler(timer_Elapsed);
            timer.Enabled =  true;
        }

         void timer_Elapsed( object sender, System.Timers.ElapsedEventArgs e)
        {
             // 模拟的做一些耗时的操作
            System.Threading.Thread.Sleep( 2000);
        }
复制代码

 

上面的例子告诉我们单线程计时器的缺点:

除非Tick事件的处理代码执行的非常快,否则UI界面会变得响应很慢。 

所以 WPF和Windows Forms的计时器都非常适合小任务,尤其是界面更新的任务。例如时钟和计数显示。否则,你需要一个多线程计时器。

 

 

参考资料:

http://www.albahari.com/threading/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值