C#中实现定时的类很多。主要是三种:
1.定义在System.Windows.Forms里
2.定义在System.Threading.Timer类里
3.定义在System.Timers.Timer类里
System.Windows.Form.Timer是应用于WinForm中的,它是通过Windows消息机制实现的,类似于VB或者Delphi中的Timer控件,内部使用API SetTimer实现。它的主要缺点是计时不精确,而且必须有消息循环,Cosole Application(控制台应用程序)无法使用。
System.Timers.Timer和System.Threading.Timer非常类似,他们是通过.Net Thread Pool实现的,轻量,计时精确,对应用程序、消息没有特别的要求。System.Timers.Timer还可以应用于WinForm,完全取代上面的Timer控件。它们的缺点是不支持直接的拖放,需要手工编码。
这里我使用的是System.Timers.Timer类,所以这里只讲解下该类,其他的类后面用到再补上。
System.Timers.Timer类
实例化:
System.Timers.Timer time = new System.Timers.Timer(1000);//这里是间隔1秒,因为单位是毫秒
另外一种实例化方法:
System.Timers.Timer time = new System.Timers.timer();
time.Interval = 2000;//设置Interval参数也可以设置间隔时间
到达后执行的函数:
time.Elapsed += new Syatem.Timers.ElapsedEventHandler(theout);//到了1秒后执行函数theout
设置相关参数:
执行次数:time.AutoReset = true;//为True则是每过1秒执行一次,为False则是只执行一次
是否执行函数:time.Enable = true;//为Ture则是执行函数theout,为False则是不执行函数theout
下面是我自己写的一个功能,具体是:需要过2秒后执行函数CheckUpdatetimer_Elapsed,该代码实在C#的控件里面写的。
函数CheckUpdatetimer_Elapsed为时间到后应该执行的函数。
private void CheckUpdatetimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { lock(locko) { if (m_PPTobjectGui.isPlaying()) { m_PPTobjectGui.pause(); } m_timer.Enabled = false; m_timer.Close(); } }
//该函数是点击按钮后执行的函数
private void cbPlay_Click(object sender, EventArgs e) { m_PPTobjectGui.set_video_time(0); m_PPTobjectGui.play(); m_timer.Interval = m_PPTobjectGui.get_interval_time() * 1000;//这里是2秒,m_PPTobjectGui.get_interval_time()等于2.
m_timer.Enabled = true;//执行
m_timer.AutoReset = false; //执行一次
}
//m_time的初始化写在界面的初始化中
private System.Timers.Timer m_timer; m_timer = new System.Timers.Timer(); m_timer.Elapsed += new ElapsedEventHandler(CheckUpdatetimer_Elapsed);
整个过程是点击按钮后,执行函数cbPlay_Click,过了2秒后执行函数CheckUpdatetimer_Elapsed,函数CheckUpdatetimer_Elapsed中的locko是锁,防止线程重入。
locko的定义也写在界面的初始化中, private object locko = new Object();
C++中实现定时器的主要方式是:SetTimer。
1.1 SetTimer简介
UINT_PTR SetTimer(
HWND hWnd,
UINT_PTR nIDEvent,
UINT uElapse, //这里的延迟时间单位是毫秒,即1000毫秒 = 1秒
TIMERPROC lpTimerFunc
);
功能:
创建或设置一个定时器。
参数:
HWND hWnd, hWnd是和timer关联的窗口句柄,此窗口必须为调用SetTimer的线程所有;如果hWnd为NULL,没有窗口和timer相关联并且nIDEvent参数被忽略。
UINT_PTR nIDEvent, nIDEvent是timer的标识,为非零值;如果hWnd为NULL则被忽略;如果hWnd非NULL而且与timer相关联的窗口已经存在一个为此标识的timer,则此次SetTimer调用将用新的timer代替原来的timer。timer标识和窗口相关,两个不同的窗口可以拥有nIDEvent相同的tiemr。
UINT uElapse, uElapse是以毫秒指定的计时间隔值。
TIMERPROC lpTimerFunc, lpTimerFunc是一个回调函数的指针,俗称TimerFunc;如果lpTimerFunc为NULL,系统将向应用程序队列发送WM_TIMER消息;如果lpTimerFunc指定了一个值,DefWindowProc将在处理WM_TIMER消息时调用这个lpTimerFunc所指向的回调函数,因此即使使用TimerProc代替处理WM_TIMER也需要向窗口分发消息。
其中TimerProc函数的原型如下:
VOID CALLBACK TimerProc(
HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime
);
注意:定时器过了多长时间需要实现的功能都写到这个函数里面,并且格式固定,参数类型和函数的返回值类型一定固定,函数的名字可以自己命名;如果该函数是一个类的成员函数,则需要声明为static类型,同时里面所用的变量也需要声明为static。
返回值:
如果hWnd为NULL,返回值为新建立的timer的ID,如果hWnd非NULL,返回一个非0整数,如果SetTimer调用失败则返回0.
通过上面的两个函数就可以创建一个时间定时器,如果想要结束时间定时器,可以通过KillTimer实现,
KillTimer函数原型为:
BOOL KillTimer(
HWND hWnd,
UINT_PTR uIDEvent
);
功能:
销毁指定的定时器。
参数:
HWND hWnd, 与特定timer相关联的窗口句柄,
UINT_PTR uIDEvent, 指定将要被销毁的timer的ID。如果hWnd不为NULL,则该参数与传递给SetTimer函数的nIDEvent相同;如果hWnd为NULL,则该参数与SetTimer函数的返回值相同。
返回值:
如果函数执行成功,返回非零值;如果执行不成功,返回零值。
示例:
类PPTManager中声明TimerProc函数为:static void CALLBACK pause(HWND hWnd, UINT nMsg, UINT_PTR nIDEvent, DWORD dwTime);
实现:
void CALLBACK VRBase::PPTManager::pause(HWND hWnd, UINT nMsg, UINT_PTR nIDEvent, DWORD dwTime) { bool isTrue = KillTimer(NULL, m_TimerID);//执行一个后关闭该定时器 if (m_timeObj != NULL && isTrue) { if (NetCollaboration::DataMonitor::Get()->isConnect()) { NetCollaboration::DataMonitor::Get()->saveStateForNetCorp("%actn%ndID%order", NetCollaboration::objGuiVideo, m_timeObj->getID(), "objectGuiVideoPause"); } else { VRNet::NodeSyncker::Get()->SetObjectGuiPause(m_timeObj); } } }
其中,m_TimerID为定时器的返回值。
定义的SetTimer为:m_TimerID = SetTimer(NULL, 3, delayTime, (TIMERPROC)pause);
因为没有窗口,所以第一个参数为null,第二个参数在这里无用,第三个参数为延迟时间,第四个参数为过了delayTime后执行的操作,m_TimerID为返回值,使用KillTimer函数时,需要使用这个返回值。
如果有窗口绑定的话,第一个参数不能为NULL,应该为窗口的句柄,函数的返回值为第二个参数,在使用KillTimer终止一个时间定时器的时候,第一个参数也应该是窗口的句柄,第二个参数为SetTimer中的
第二个参数。
注意:m_TimerID为Static,m_timeObj也为Static类型。
以上是我最近使用定时器的一些总结,后面如果还有其他更好的方法,会在添加。