定期执行受计算限制的异步操作

  System.Threading命名空间中定义了一个Timer类,可使用这个类让CLR定期地调用方法。构建Timer类的实例时,实际是在告诉CLR我们希望一个方法在指定的时间内被再次调用。Timer类提供了几个非常相似的构造器:

public sealed class Timer : MarshalByRefObject, IDisposable
{
public Timer(TimerCallback callback, Object state, int dueTime, int period);
public Timer(TimerCallback callback, Object state, UInt32 dueTime, UInt32 period);
public Timer(TimerCallback callback, Object state, UInt64 dueTime, UInt64 period);
public Timer(TimerCallback callback, Object state, TimeSpan dueTime, TimeSpan period);
}
  参数callback用来标识希望线程池中线程回调的方法。我们所编写的回调线程必须与System.Threading.TimerCallback委托类型匹配,该委托类型的定义如下所示:
delegate void TimerCallback(object state);

  state参数允许我们将状态数据传递给回调方法。dueTime参数指定在第一次调用回调方法时需要等待多少毫秒。period参数指定回调方法被调用的时间间隔(以毫秒为单位)。如果该参数传递的值为Timeout.Infinite(-1),那么线程池中的线程只会调用回调方法一次。

  从内部实现上讲,所有的Timer对象只使用CLR的一个线程,该线程知道下一个Timer对象什么时候到达。当下一个Timer对象到达后,CLR的线程就会醒来,并在其内部调用ThreadPool的QueueUserWorkItem方法将一个条目加入到线程池的队列中,从而导致回调方法被调用。如果回调方法需要较长的时间来执行,那么定时器可能会再次触发。这可能导致多个线程池中的对象同时执行回调方法。请注意这一点,如果我们的方法访问了任何共享数据,就需要增加一些线程同步锁来防止数据被破坏。

  Timer类还提供了一些额外的方法(Change和Dispose),当方法被回调时,这些方法允许我们与CLR进行通信从而对定时器进行修改。Change方法允许我们更改或重新设置Timer对象的启动时间和间隔。Dispose方法允许我们完全取消定时器,还可以在所有挂起的回调方法完成时选择性的通知notifyObject参数标识的内核对象。

  当Timer对象被执行垃圾收集时,CLR就会取消定时器,以便定时器不再继续触发。因此,在使用Timer对象时,一定要确保有一个变量来引用Timer对象,从而保持Timer对象继续存活,否则回调方法就不会再被调用。

  下面的代码演示了Timer的使用方法:

using System;
using System.Threading;

public static class Program
{
public static void Main()
{
Console.WriteLine(
"Main thread: starting a timer");
Timer t
= new Timer(ComputeBoundOp, 5, 0, 2000);

Console.WriteLine(
"Main thread: Doing other work here...");
Thread.Sleep(
10000); //模拟其他工作10秒
t.Dispose(); //取消定时器
}

//该方法签名必须与TimerCallback委托类型匹配
private static void ComputeBoundOp(object state)
{
//该方法由线程池中的线程执行
Console.WriteLine("In ComputeBoundOp: state = {0}", state);
Thread.Sleep(
1000); //模拟其他工作1秒

//方法返回后,线程就回到线程池中,然后等待执行另一个任务
}
}

三个定时器的史话

  FCL中实际提供了三个定时器。

  System.Threading的Timer类:该定时器就是前一节所讨论的定时器,希望在另一个线程上定时执行后台任务时,这个定时器是最好的定时器。

  System.Windows.Forms的Timer类:构建一个该类的实例可以告诉Windows将定时器与调用线程关联。随着定时器的触发,Windows将一个定时器消息(WM_TIMER)插入到线程的消息队列中。调用线程必须执行一个消息泵,从而提取消息,并将它们分派到期望的回调方法中。注意,所有这些工作都是由一个线程完成的--设置定时器的线程保证是执行回调方法的线程。这同样意味着我们的定时器方法不能被多个线程同时执行。

  System.Timers的Timer类:该定时器基本上是对System.Threading的Timer类的包装,当定时器时间到期后,将导致CLR将事件加入线程池的队列中。System.Timers.Timer类派生自System.ComponentModel的Component类,Component类允许将这些定时器对象放置在VS设计界面上。不建议使用该类,因为该类今后有可能被移除。

posted on 2011-07-10 23:42  辛勤的代码工  阅读(949)  评论(0编辑  收藏  举报