不像我开始描述的两个定时器类SystemThreadingTimer有四个重载构造函数就像下面这样
public Timer(TimerCallback callback
object state
long dueTime
long period);
public Timer(TimerCallback callback object state UInt dueTime UInt period);
public Timer(TimerCallback callback object state int dueTime int period);
public Timer(TimerCallback callback object state TimeSpan dueTime TimeSpan period);
第一个参数(callback)要求一个TimerCallback的委托它指向一个方法该方法具有下面的结构
public void TimerCallback(object state);
第二个参数(state)可以为空或者是包含程序规范信息的对象在每一个定时器事件被调用时该state对象作为一个参数传递给你的定时回调函数记住定时回调功能是在一个工作者线程上执行的所以你必须确保访问state对象的线程安全
第三个参数(dueTime)让你定义一个引发初始定时器事件的时间你可指定一个立即开始定时器或者阻止定时器自动的开始你可以使用SystemThreadingTimeoutInfinite常量
第四个参数(period)让你定义一个回调函数被调用的时间间隔(毫秒)给该参数定义一个或者TimeoutInfinite可以阻止后续的定时器事件调用
一旦构造函数被调用你仍然可以通过Change方法改变dueTime和period该方法有下面四种重载形式
public bool Change(int dueTime
int period);public bool Change(uint dueTime
uint period);public bool Change(long dueTime
long period);public bool Change(TimeSpan dueTime
TimeSpan period);
下面是我在例子程序中用到的开始和停止该定时器的代码
//Initialize the timer to not start automatically
System
Threading
Timer tmrThreadingTimer = newSystem
Threading
Timer(new TimerCallback(tmrThreadingTimer_TimerCallback)
null
System
Threading
Timeout
Infinite
);
//Manually start the timertmrThreadingTimerChange( );
//Manually stop the timertmrThreadingTimerChange(TimeoutInfinte TimeoutInfinite);
正如你所期望的那样通过选择SystemThreadingTimer类运行例子程序会产生同你看到的SystemTimersTimer类一样的输出结果因为TimerCallback功能也是在工作者线程上被调用没有一个跳动被跳过(假设有工作者线程可用)Figure 显示了例子程序的输出结果
不像SystemTimersTimer类没有与SynchronizingObject相对应的属性被提供任何请求访问UI控件的操作都必须通过控件的Invoke或BeginInvoke方法被列集
定时器的线程安全编程
为了最大限度的代码重用三种不同类型的定时器事件都调用了同样的ShowTimerEventFired方法下面就是三个定时器事件的处理函数
private void tmrWindowsFormsTimer_Tick(object sender SystemEventArgse)
{
ShowTimerEventFired(DateTimeNow GetThreadName());
}
private void tmrTimersTimer_Elapsed(object sender SystemTimersElapsedEventArgse){
ShowTimerEventFired(DateTimeNow GetThreadName());
}
private void tmrThreadingTimer_TimerCallback(object state){ ShowTimerEventFired(DateTimeNow GetThreadName());
}
正如你所看到的ShowTimerEventFired方法采用当前时间和当前线程名字作为参数为了区别工作者线程和UI线程在例子程序的主入口点设置CurrentThread对象的名字属性为UIThreadGetThreadName帮助函数返回ThreadCurrentThreadName值或者当ThreadCurrentThreadIsThreadPoolThread属性为真时返回WorkerThread
因为SystemTimersTimer和SystemThreadingTimer的定时器事件都是在工作者线程上执行的所以在事件处理函数中的任何用户交互代码都不是马上进行的而是被列集等候返回到UI线程上进行处理为了这样做我创建了一个ShowTimerEventFiredDelegate委托调用
private delegate void ShowTimerEventFiredDelegate (DateTime eventTime
string threadName);
[] [] [] []