c#: 四种定时器

环境:

  • window 10
  • vs2016 16.5.1
  • .netcore 3.1.1

实验目的:
实验c#中的多线程定时器和单线程定时器

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

在Framework中存在着4种定时器:其中分为两类:多线程计时器和特殊目的的单线程计时器。多线程计时器比较强大,精确,而且可扩展性强;单线程计时器比较安全,对于更新 Windows Forms controls或者WPF这种简单任务来说更方便。

一、多线程计时器

1.1 System.Threading.Timer

参照官方文档:Timer 类
System.Threading.Timer是最简单的多线程计时器,由线程池线程服务,简单且对资源要求不高。在下面的例子中,定时器在5秒后开始定时1秒的调用Tick方法。

using System;
using System.Collections;
using System.Data;
using System.IO;
using System.Threading;
namespace TestDI
{
    class Program
    {
        public static void Main(string[] args)
        {
            System.Threading.Timer timer = new Timer((state) =>
            {
                state += $"任务线程:{Thread.CurrentThread.ManagedThreadId} " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " isThreadPool:" + Thread.CurrentThread.IsThreadPoolThread;
                Console.WriteLine(state);
            }, "hello", 5000, 1000);

            Console.WriteLine($"主线程:{Thread.CurrentThread.ManagedThreadId}");
            Console.ReadLine();
        }
    }
}

输出效果:
在这里插入图片描述
可以看出,确实是多线程执行!

注意:只要您使用 Timer,就必须保留对它的引用。 与任何托管对象一样,当不存在任何引用时,Timer 可能会进行垃圾回收。 即使 Timer 仍处于活动状态,也不会阻止收集它。

1.2 System.Timers.Timer

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

  • 实现了Component,所以可以在设计器显示。
  • 代替Change方法的一个Interval属性
  • 代替callback委托的一个Elapsed事件
  • 增加Start/Stop方法控制开启和停止

直接看使用示例:

using System;
using System.Collections;
using System.Data;
using System.IO;
using System.Threading;
namespace TestDI
{
    class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine($"主线程:{Thread.CurrentThread.ManagedThreadId}");
            System.Timers.Timer timer = new System.Timers.Timer()
            {
                Interval = 1000,
                Enabled = false
            };
            timer.Elapsed += (state, e) =>
                {
                    Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}, 任务线程:{Thread.CurrentThread.ManagedThreadId},IsThreadPoolThread:{Thread.CurrentThread.IsThreadPoolThread},state={state}");
                };
            Console.WriteLine("等待主线程开启定时器!");
            Thread.Sleep(2000);
            timer.Start();
            Console.WriteLine("主线程已开启定时器!");
            Thread.Sleep(10 * 1000);
            timer.Stop();
            Console.WriteLine("主线程已关闭定时器!");
            Console.ReadLine();
        }
    }
}

输出效果:
在这里插入图片描述

二、单线程计时器

单线程计时器是被设计成属于他们执行环境的计时器,如果你在一个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。

缺点:

  • 由於单线程执行,所以除非Tick事件的处理代码执行的非常快,否则UI界面会变得响应很慢。

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

2.1 System.Windows.Forms.Timer(Windows Forms Timer)

winform中最常用,不再演示。

2.2 System.Windows.Threading.DispatcherTimer(WPF timer)

用在wpf中。。。

参考资料:

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

CLR Via C# 3.0

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章