在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
如果你需要使用规律的时间间隔重复执行一些方法,最简单的方式是使用定时器(timer)。与下边的例子相比,定时器可以便捷、高效地使用内存和资源: new Thread (delegate() { while (enabled) { DoSomeAction(); Thread.Sleep (TimeSpan.FromHours (24)); } }).Start(); 这不仅仅会永久占用一个线程,而且如果没有额外的代码,DoSomeAction每天都会发生在更晚的时间。定时器解决了这些问题。 .NET Framework 提供了 4 种定时器。下边两个类是通用的多线程定时器: (1)System.Threading.Timer (3)System.Windows.Forms.Timer (Windows Forms 的定时器) 1.多线程定时器Permalink System.Threading.Timer是最简单的多线程定时器:它仅仅有一个构造方法和两个普通方法(取悦于极简主义者,还有本书作者!)。在接下来的例子中,一个定时器在 5 秒钟之后调用Tick方法来打印 “ tick… “,之后每秒打印一次直到用户按下回车键: using System; using System.Threading; class Program { static void Main() { // 首次间隔 5000ms,之后间隔 1000ms Timer tmr = new Timer (Tick, "tick...", 5000, 1000); Console.ReadLine(); tmr.Dispose(); // 停止定时器并执行清理工作 } static void Tick (object data) { // 这里运行在一个线程池线程上 Console.WriteLine (data); // 打印 "tick..." } } 之后可以通过调用Change方法来改变定时器的时间间隔。如果你希望定时器只触发一次,可以指定Timeout.Infinite作为构造方法的最后一个参数。 .NET Framework 在System.Timers命名空间下提供了另一个名字相同的定时器类。它只是封装了 System.Threading.Timer,并在使用完全相同的底层引擎的前提下提供额外的便利。下面是增加功能的简介: (1)实现了Component,允许用于 Visual Studio 的设计器中。 using System; using System.Timers; // 命名空间是 Timers 而不是 Threading class SystemTimer { static void Main() { Timer tmr = new Timer(); // 无需任何参数 tmr.Interval = 500; tmr.Elapsed += tmr_Elapsed; // 使用事件代替委托 tmr.Start(); // 开启定时器 Console.ReadLine(); tmr.Stop(); // 停止定时器 Console.ReadLine(); tmr.Start(); // 重启定时器 Console.ReadLine(); tmr.Dispose(); // 永久停止定时器 } static void tmr_Elapsed (object sender, EventArgs e) { Console.WriteLine ("Tick"); } } 多线程定时器使用线程池来允许少量线程服务多个定时器。这意味着,回调方法或Elapsed事件每次可能会在不同的线程上触发。此外,不论之前的Elapsed是否完成执行,Elapsed总是几乎按时触发。因此,回调方法或事件处理器必须是线程安全的。 多线程定时器的精度依赖于操作系统,通常是在 10-20 ms 的区间。如果需要更高的精度,你可以使用本地互操作(native interop)来调用 Windows 多媒体定时器,可以让精度提升到 1 ms。它定义在 winmm.dll 中,首先调用timeBeginPeriod来通知操作系统你需要更高的定时器精度,然后调用timeSetEvent来启动多媒体定时器。当使用完成后,调用timeKillEvent停止定时器,最后调用timeEndPeriod通知操作系统你不在需要更高的定时器精度了。可以通过搜索关键字 dllimport winmm.dll timesetevent 在网上找到完整的例子。 2.单线程定时器Permalink .NET Framework 提供了两个定时器,为消除WPF 和 Windows Forms 应用程序的线程安全问题而设计: System.Windows.Threading.DispatcherTimer(WPF) 它们暴露的成员都像System.Timers.Timer一样(Interval、Tick、Start和Stop),并且用法也类似。但是不同之处在于其内部是如何工作的。它们不是使用线程池来产生定时器事件,WPF 和 Windows Forms 定时器依赖于 UI 模型的底层消息循环机制(message pumping mechanism)。意味着Tick事件总是在创建该定时器的那个线程触发,在通常的程序中,它也就是管理所有 UI 元素和控件的那个线程。这有很多好处: 单线程计时器比较安全,对于更新 Windows Forms controls或者WPF这种简单任务来说更方便。在WPF或Windows Forms中安全的调用方法的SynchronizingObject对象。 你可以不必考虑线程安全。 除非Tick事件处理器执行的很快,否则 UI 会失去响应。 在精度方面,单线程定时器与多线程定时器类似(几十毫秒),但是通常精度更低,因为它们会被其它 UI 请求(或其它定时器事件)推迟。 单线程计时器基于Windows消息循环,应用程序会同步的处理计时器的消息。会发现UI界面相应速度比较慢。解决这个问题的方法是使用多线程计时器。
|
请发表评论