最近在学习C#,创建的工程是WPF或控制台程序。在WPF中用到了定时器。今天在CSDN中找了下,就复制加总结下吧。

C#中定时器有四个,分两种。一种是多线程的,一种是单线程的。
多线程计时器:

 1. System.Threading.Timer 
2. System.Timers.Timer

单线程计时器:

1. System.Windows.Forms.Timer(Windows Forms Timer)
2. System.Windows.Threading.DispatcherTimer(WPF timer);

多线程计时器比较强大,精确,而且可扩展性强。System.Threading.Timer是最简单的多线程计时器。

.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属性。

单线程计时器比较安全,对于更新 Windows Forms controls或者WPF这种简单任务来说更方便。在WPF或Windows Forms中安全的调用方法的SynchronizingObject对象。
单线程计时器是被设计成属于他们执行环境的计时器,如果你在一个Windows服务应用程序中使用Windows Forms的Timer,timer 事件并不会被触发,只有在对应的环境下才会被触发。
像System.Timers.Timer一样,他们也提供了相同的成员(Interval,Tick,Start,Stop),但是他们内部的工作原理不同,WPF和Windows Forms的计时器使用消息循环机制来取代线程池产生消息的机制。
这意味着Tick事件总是在创建timer的那个线程上执行,同时也意味着如果上一个Tick消息还未被处理,即使时间超过了间隔时间,在消息循环中也只存在一个Tick消息。
你可以忘记线程安全。一个Tick事件在前一个Tick事件被处理完毕前不会被触发。你可以直接在Tick事件处理代码中更新控件,不需要调用Control.Invoke或Dispatcher.Invoke.

单线程计时器基于Windows消息循环,应用程序会同步的处理计时器的消息。会发现UI界面相应速度比较慢。解决这个问题的方法是使用多线程计时器。
单线程计时器的缺点:除非Tick事件的处理代码执行的非常快,否则UI界面会变得响应很慢。所以 WPF和Windows Forms的计时器都非常适合小任务,尤其是界面更新的任务。例如时钟和计数显示。否则,你需要一个多线程计时器

下边为Timers和DispatcherTimer写的小demo。异想天开的以为可以运行起来。发现Timers有点问题。暂时把代码注释掉了。只保留DispatcherTimer的代码。问题暂时还没找出来,对C#的多线程还不了解。郁闷啊。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Timers;
using System.Windows.Threading;

namespace TimingTest
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        private Timer timer;
        private DispatcherTimer disTimer;
        private int timeNum =0;

        public MainWindow()
        {
            InitializeComponent();

            Init();
        }

        private void Init()
        {
            timerBtn.Click += timerClickHandler;
            distimerBtn.Click += distimerClickHandler;
            stopBtn.Click += stopTimerHandler;

         //   timer = new Timer();
         //   timer.Elapsed += new ElapsedEventHandler(timerHandler);
         //   timer.Interval = 1000;
         //   timer.Enabled = true;

     
            disTimer = new DispatcherTimer();
            disTimer.Tick += disTimerHandler;
            disTimer.Interval = TimeSpan.FromSeconds(1);
          
        }

        private void timerHandler(object sender,ElapsedEventArgs e)
        {
            timeNum++;
            printf("timer");
        }
        private void disTimerHandler(object sender,EventArgs e)
        {
            timeNum++;
            printf("disTimer");
        }

        private void printf(string huo)
        {
           
            box.AppendText("这个是 " + huo + "在定时,timeNum :" + timeNum.ToString() + "\n");
        }

        private void stopTimerHandler(object sender, RoutedEventArgs e)
        {
            stopTime();
        }

        private void stopTime()
        {
            //怎么没找到队定时器当前的状态的属性呢。郁闷了。。。
            timer.Stop();
            disTimer.Stop();
        }

        private void timerClickHandler(object sender, RoutedEventArgs e)
        {
            timer.Start();
        }

        private void distimerClickHandler(object sender, RoutedEventArgs e)
        {
            disTimer.Start();
        }
    }
}

 

文章参考来源