发布网友 发布时间:2023-04-22 12:22
共1个回答
热心网友 时间:2023-11-10 14:49
不像我开始描述的两个定时器类 System Threading Timer有四个重载构造函数 就像下面这样
public Timer(TimerCallback callback object state long eTime long period);public Timer(TimerCallback callback object state UInt eTime UInt period);public Timer(TimerCallback callback object state int eTime int period);public Timer(TimerCallback callback object state TimeSpan eTime TimeSpan period);第一个参数(callback)要求一个TimerCallback的委托 它指向一个方法 该方法具有下面的结构
public void TimerCallback(object state);
第二个参数(state)可以为空或者是包含程序规范信息的对象 在每一个定时器事件被调用时该state对象作为一个参数传递给你的定时回调函数 记住定时回调功能是在一个工作者线程上执行的 所以你必须确保访问state对象的线程安全
第三个参数(eTime)让你定义一个引发初始定时器事件的时间 你可指定一个 立即开始定时器或者阻止定时器自动的开始 你可以使用System Threading Timeout Infinite常量
第四个参数(period)让你定义一个回调函数被调用的时间间隔(毫秒) 给该参数定义一个 或者Timeout Infinite可以阻止后续的定时器事件调用
一旦构造函数被调用 你仍然可以通过Change方法改变eTime和period 该方法有下面四种重载形式
public bool Change(int eTime int period);public bool Change(uint eTime uint period);public bool Change(long eTime long period);public bool Change(TimeSpan eTime 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 timer tmrThreadingTimer Change( );//Manually stop the timer tmrThreadingTimer Change(Timeout Infinte Timeout Infinite);正如你所期望的那样 通过选择System Threading Timer类运行例子程序会产生同你看到的System Timers Timer类一样的输出结果 因为TimerCallback功能也是在工作者线程上被调用 没有一个跳动被跳过(假设有工作者线程可用) Figure 显示了例子程序的输出结果
不像System Timers Timer类 没有与SynchronizingObject相对应的属性被提供 任何请求访问UI控件的操作都必须通过控件的Invoke或BeginInvoke方法被列集
定时器的线程安全编程
为了最大限度的代码重用 三种不同类型的定时器事件都调用了同样的ShowTimerEventFired方法 下面就是三个定时器事件的处理函数
private void tmrWindowsFormsTimer_Tick(object sender System EventArgse){ ShowTimerEventFired(DateTime Now GetThreadName());}private void tmrTimersTimer_Elapsed(object sender System TimersElapsedEventArgse){ ShowTimerEventFired(DateTime Now GetThreadName());}private void tmrThreadingTimer_TimerCallback(object state){ ShowTimerEventFired(DateTime Now GetThreadName());}
正如你所看到的 ShowTimerEventFired方法采用当前时间和当前线程名字作为参数 为了区别工作者线程和UI线程 在例子程序的主入口点设置CurrentThread对象的名字属性为 UIThread GetThreadName帮助函数返回Thread CurrentThread Name值或者当Thread CurrentThread IsThreadPoolThread属性为真时返回 WorkerThread
因为System Timers Timer和System Threading Timer的定时器事件都是在工作者线程上执行的 所以在事件处理函数中的任何用户交互代码都不是马上进行的 而是被列集等候返回到UI线程上进行处理 为了这样做 我创建了一个ShowTimerEventFiredDelegate委托调用
private delegate void ShowTimerEventFiredDelegate (DateTime eventTime string threadName); lishixin/Article/program/net/201311/15305