一、使用计时器
在某些情况下,可能不需要使用单独的线程。如果应用程序需要定期执行简单的与 UI 有关的操作,则应该考虑使用进程计时器。有时,在智能客户端应用程序中使用进程计时器,以达到下列目:
• |
按计划定期执行操作。 |
• |
在使用图形时保持一致的动画速度(而不管处理器的速度)。 |
• |
监视服务器和其他的应用程序以确认它们在线并且正在运行。 |
.NET Framework 提供三种进程计时器:
• |
System.Window.Forms.Timer |
• |
System.Timers.Timer |
• |
System.Threading.Timer |
如果想要在 Windows 窗体应用程序中引发事件,System.Window.Forms.Timer 就非常有用。它经过了专门的优化以便与Windows 窗体一起使用,并且必须用在 Windows 窗体中。它设计成能用于单线程环境,并且可以在 UI 线程上同步操作。这就意味着该计时器从来不会抢占应用程序代码的执行(假定没有调用 Application.DoEvents),并且对与 UI 交互是安全的。
System.Timers.Timer 被设计并优化成能用于多线程环境。与 System.Window.Forms.Timer 不同,此计时器调用从 CLR 线程池中获得的辅助线程上的事件处理程序。在这种情况下,应该确保事件处理程序不与 UI 交互。System.Timers.Timer 公开了可以模拟 System.Windows.Forms.Timer 中的行为的 SynchronizingObject 属性,但是除非需要对事件的时间安排进行更精确的控制,否则还是应该改为使用 System.Windows.Forms.Timer。
System.Threading.Timer 是一个简单的轻量级服务器端计时器。它并不是内在线程安全的,并且使用起来比其他计时器更麻烦。此计时器通常不适合 Windows 窗体环境。表 1.1 列出了每个计时器的各种属性。
表 1.1 进程计时器属性
属性 |
System.Windows.Forms |
System.Timers |
System.Threading |
计时器事件运行在什么线程中? |
UI 线程 |
UI 线程或辅助线程 |
辅助线程 |
实例是线程安全的吗? |
否 |
是 |
否 |
需要 Windows 窗体吗? |
是 |
否 |
否 |
最初的计时器事件可以调度吗? |
否 |
否 |
是 |
二、使用Thread进行异步操作
使用Thread进行异步操作的方法如下所示,需要注意的就是IsBackground默认为false,也就是该线程对调用它的线程不产生依赖,当调用线程退出时该线程也不会结束。因此需要将IsBackground设置为true以指明该线程是后台线程,这样当主线程退出时该线程也会结束。另外跨线程操作UI还是要借助Dispatcher.BeginInvoke(),如果需要阻塞UI线程可以使用Dispatcher.Invoke()。
使用 Thread 类可以显式管理线程。这包括 CLR 创建的线程和进入托管环境执行代码的 CLR 以外创建的线程。CLR 监视其进程中曾经在 .NET Framework 内执行代码的所有线程,并且使用 Thread 类的实例来管理它们。
只要有可能,就应该使用 ThreadPool 类来创建线程。然而,在一些情况下,您还是需要创建并管理您自己的线程,而不是使用 ThreadPool 类。
在下面的情况下,使用 Thread 对象:
• |
需要具有特定优先级的任务。 |
• |
有可能运行很长时间的任务(这样可能阻塞其他任务)。 |
• |
需要确保只有一个线程可以访问特定的程序集。 |
• |
需要有与线程相关的稳定标识。 |
Thread 对象包括许多属性和方法,它们可