none
.NET中各Timer的区别 RRS feed

  • 问题

  • 我发现.NET窗体应用程序里面至少有三种Timer,分别是

    System.Timers.Timer
    System.Windows.Forms.Timer
    System.Threading.Timer

     System.Windows.Forms.Timer在窗体设计器里面就有了,Threading.Timer似乎和线程有关,而Timers.TImer,单独放到一个名称空间里,显得更加专业……

    也不知道我的分析对不对,请问各位老师这些 Timer 有什么区别?

    2011年4月9日 4:10

答案

  • 您好

    您可以參考

    三種時間人《.NET中的Timer(1)》

    http://www.dotblogs.com.tw/billchung/archive/2009/04/18/8044.aspx

    三種時間人《.NET中的Timer(2)》

    http://www.dotblogs.com.tw/billchung/archive/2009/04/19/8052.aspx

    三種時間人《.NET中的Timer(3)》

    http://www.dotblogs.com.tw/billchung/archive/2009/05/03/8277.aspx


    歡迎參觀我的Blog.NET菜鳥自救會
    2011年4月10日 16:12
  • Visual Studio 2003的工具箱里面默认提供了System.Windows.Forms.Timer和System.Timers.Timer两种,而Visual Studio 2005中确只默认提供了System.Windows.Forms.Timer这一种。这里简单的介绍一下这两种Timer的区别。

    System.Windows.Forms.Timer是使用得比较多的Timer,Timer Start之后定时(按设定的Interval)调用挂接在Tick事件上的EvnetHandler。在这种Timer的EventHandler中可以直接获取和修改UI元素而不会出现问题--因为这种Timer实际上就是在UI线程自身上进行调用的。也正是因为这个原因,导致了在Timer的EventHandler里面进行长时间的阻塞调用,将会阻塞界面响应的后果。下面是一个简单的例子:

    public class MainForm : Form
    {
    private void MainForm_Load(object sender, EventArgs e)
    {
    timer.Interval = 1000;
    timer.Tick += delegate(object o, EventArgs args)
    {
    DoWork();
    };
    timer.Start();
    }
    
    private void DoWork()
    {
    for (int i = 0; i < 10; i++)
    {
    System.Threading.Thread.Sleep(1000);
    }
    }
    System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
    }

     

    在这个例子中,DoWork方法里面将会阻塞10秒,在这10秒之内,UI将会失去响应。而通过使用System.Timers.Timer,就可以解决这个问题。因为System.Timers.Timer是在.NET的Thread Pool上面运行的,而不是直接在UI Thread上面运行,所以在这种Timer的EventHandler里面进行耗时较长的计算不会导致UI失去响应。但是这里有两个地方需要注意:

    1. 因为一般来说System.Timers.Timer不是运行在UI Thread上面的,所以如果要在这种Timer的EventHandler里面更新UI元素的话,需要进行一次线程切换,在WinForm开发中一般通过UI元素的Invoke方法完成:
      private void DoWork()
        {
        for (int i = 0; i < 10; i++)
        {
        System.Threading.Thread.Sleep(1000);
        }
        this.Invoke(new UpdateUICallBack(UpdateUI));
        }
        
        private delegate void UpdateUICallBack();
        
        private void UpdateUI()
        {
        } 
    2. System.Timers.Timer有一个Property:SynchronizingObject 。如果设置了这个Property(一般是某个Form),那么之后对Timer挂接的EventHandler的调用将会在创建这个UI元素的线程上进行(一般来说就是UI线程)。值得注意的是,如果你通过WinForm设计器把System.Timers.Timer拖放到Form上,那么这个Property将会自动被设置。此时这种Timer就和System.Windows.Forms.Timer的效果一样:长调用将会阻塞界面。

    • 已标记为答案 Flysha 2011年4月11日 8:03
    2011年4月9日 16:49
  • System.Windows.Forms.Timer 最好不用,因为她和UI在一个线程上,所以会被UI 中的事件干扰。

    Timers.Timer 是有自己的线程,但需要你自己创建SynchronizingObject 来和其他线程同信, 用起来有点复杂。

    System.Threading.Timer 有自带的SynchronizationContext, 直接可以用CallbackDelegate 和其他Thread 同信。是最好的

    以下英文版的说明很详细

    Comparing the Timer Classes in the .NET Framework Class Library

    http://msdn.microsoft.com/zh-cn/magazine/cc164015(en-us).aspx

    • 已标记为答案 Flysha 2011年4月11日 8:04
    2011年4月10日 13:40

全部回复

  • 主要是使用场景不一样,功能都差不多。

    比如你在建立一个windows server 的时候 这个时候是没有界面的,就只能用system.timers.timer了。相反在windows form上就可以使用第二个控件。方便直观。


    family as water
    2011年4月9日 14:16
  • Visual Studio 2003的工具箱里面默认提供了System.Windows.Forms.Timer和System.Timers.Timer两种,而Visual Studio 2005中确只默认提供了System.Windows.Forms.Timer这一种。这里简单的介绍一下这两种Timer的区别。

    System.Windows.Forms.Timer是使用得比较多的Timer,Timer Start之后定时(按设定的Interval)调用挂接在Tick事件上的EvnetHandler。在这种Timer的EventHandler中可以直接获取和修改UI元素而不会出现问题--因为这种Timer实际上就是在UI线程自身上进行调用的。也正是因为这个原因,导致了在Timer的EventHandler里面进行长时间的阻塞调用,将会阻塞界面响应的后果。下面是一个简单的例子:

    public class MainForm : Form
    {
    private void MainForm_Load(object sender, EventArgs e)
    {
    timer.Interval = 1000;
    timer.Tick += delegate(object o, EventArgs args)
    {
    DoWork();
    };
    timer.Start();
    }
    
    private void DoWork()
    {
    for (int i = 0; i < 10; i++)
    {
    System.Threading.Thread.Sleep(1000);
    }
    }
    System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
    }

     

    在这个例子中,DoWork方法里面将会阻塞10秒,在这10秒之内,UI将会失去响应。而通过使用System.Timers.Timer,就可以解决这个问题。因为System.Timers.Timer是在.NET的Thread Pool上面运行的,而不是直接在UI Thread上面运行,所以在这种Timer的EventHandler里面进行耗时较长的计算不会导致UI失去响应。但是这里有两个地方需要注意:

    1. 因为一般来说System.Timers.Timer不是运行在UI Thread上面的,所以如果要在这种Timer的EventHandler里面更新UI元素的话,需要进行一次线程切换,在WinForm开发中一般通过UI元素的Invoke方法完成:
      private void DoWork()
        {
        for (int i = 0; i < 10; i++)
        {
        System.Threading.Thread.Sleep(1000);
        }
        this.Invoke(new UpdateUICallBack(UpdateUI));
        }
        
        private delegate void UpdateUICallBack();
        
        private void UpdateUI()
        {
        } 
    2. System.Timers.Timer有一个Property:SynchronizingObject 。如果设置了这个Property(一般是某个Form),那么之后对Timer挂接的EventHandler的调用将会在创建这个UI元素的线程上进行(一般来说就是UI线程)。值得注意的是,如果你通过WinForm设计器把System.Timers.Timer拖放到Form上,那么这个Property将会自动被设置。此时这种Timer就和System.Windows.Forms.Timer的效果一样:长调用将会阻塞界面。

    • 已标记为答案 Flysha 2011年4月11日 8:03
    2011年4月9日 16:49
  • 谢谢!

    那请问System.Threading.Timer和上面的有什么区别吗?

    2011年4月9日 22:44
  • System.Windows.Forms.Timer 最好不用,因为她和UI在一个线程上,所以会被UI 中的事件干扰。

    Timers.Timer 是有自己的线程,但需要你自己创建SynchronizingObject 来和其他线程同信, 用起来有点复杂。

    System.Threading.Timer 有自带的SynchronizationContext, 直接可以用CallbackDelegate 和其他Thread 同信。是最好的

    以下英文版的说明很详细

    Comparing the Timer Classes in the .NET Framework Class Library

    http://msdn.microsoft.com/zh-cn/magazine/cc164015(en-us).aspx

    • 已标记为答案 Flysha 2011年4月11日 8:04
    2011年4月10日 13:40
  • 您好

    您可以參考

    三種時間人《.NET中的Timer(1)》

    http://www.dotblogs.com.tw/billchung/archive/2009/04/18/8044.aspx

    三種時間人《.NET中的Timer(2)》

    http://www.dotblogs.com.tw/billchung/archive/2009/04/19/8052.aspx

    三種時間人《.NET中的Timer(3)》

    http://www.dotblogs.com.tw/billchung/archive/2009/05/03/8277.aspx


    歡迎參觀我的Blog.NET菜鳥自救會
    2011年4月10日 16:12
  • .net framwork内部类

    winform控件,多线程。


    胡超
    2011年4月10日 16:58