1. windows平臺用微軟提供的多媒體定時器。
2. linux平臺用select方案。
多媒體定時器方案:
Visual C++中提供了很多關於時間操作的函數,利用它們控制程序能夠精確地完成定時和計時操作。Visaul C++中的WM_TIMER消息映射能進行簡單的時間控制。首先調用函數SetTimer()設置定時間隔(退出程序時別忘了調用和SetTimer()配對使用的KillTimer()函數),如SetTimer(0,200,NULL)即爲設置200ms的時間間隔。然後在應用程序中增加定時響應函數OnTimer(),並在該函數中添加響應的處理語句,用來完成到達定時時間的操作。這種定時方法非常簡單,但其定時功能如同Sleep()函數的延時功能一樣,精度非常低,只可以用來實現諸如位圖的動態顯示等對定時精度要求不高的情況。
微軟公司在其多媒體Windows中提供了精確定時器的底層API支持。利用多媒體定時器可以很精確地讀出系統的當前時間,並且能在非常精確的時間間隔內完成一個事件、函數或過程的調用。利用多媒體定時器的基本功能,可以通過兩種方法實現精確定時。1)使用timeGetTime()函數,該函數定時精度爲ms級,返回從Windows啓動開始所經過的時間。由於使用該函數是通過查詢的方式進行定時控制的,所以,應該建立定時循環來進行定時事件的控制。2)使用timeSetEvent()函數,該函數原型如下:
MMRESULT timeSetEvent(UINT uDelay,UINT uResolution,LPTIMECALLBACK lpTimeProc,DWORD dwUser,UINT fuEvent);
該函數的參數說明如下:參數uDelay表示延遲時間;參數uResolution表示時間精度,在Windows中缺省值爲1ms;lpTimeProc表示回調函數,爲用戶自定義函數,定時調用; 參數dwUser表示用戶提供的回調數據;參數fuEvent爲定時器的事件類型,TIME_ONESHOT表示執行一次;TIME_PERIODIC:週期性執行。具體應用時,可以通過調用timeSetEvent()函數,將需要週期性執行的任務定義在lpTimeProc回調函數中(如:定時採樣、控制等),從而完成所需處理的事件。需要注意的是:任務處理的時間不能大於週期間隔時間。另外,在定時器使用完畢後,應及時調用timeKillEvent()將之釋放。
#ifdef WIN32
if (NULL != g_TimerID)
{
MMRESULT ret;
ret = timeKillEvent(g_TimerID);
if (TIMERR_NOERROR != ret)
{
g_debug("timeKillEvent failed.");
}
else
{
g_TimerID = NULL;
}
}
{
g_TimerID = timeSetEvent(40, 1, //40毫秒
(LPTIMECALLBACK) DoProcess,
(DWORD)this,TIME_PERIODIC);
if (NULL == g_TimerID)
{
g_debug("create mm timer failed.");
}
}
#endif
select方案:
struct timeval tv;
struct sched_param task_param;
//提高優先級
task_param.sched_priority = 80;
if( pthread_setschedparam(pthread_self(), SCHED_FIFO, &task_param) )
{
g_debug("set task priority failed: %s/n", strerror(errno));
}
BOOL32 bActive = TRUE;
while(bActive)
{
bActive = GetActiveStatus();
//定時器
for (l32 i = 0; i < 40; i++) //40毫秒
{
tv.tv_sec = 0;
tv.tv_usec = 1000;
select(0, NULL, NULL, NULL, &tv);
}
g_mutex_lock((GMutex*)(ptLock));
g_cond_signal((GCond*)(ptCond));
g_mutex_unlock((GMutex*)(ptLock));
}
Select方案關鍵點:
1) 用select作定時器要單獨起線程並且提高線程優先級。
2) 線程中除了給信號不做其它任何有負載的工作。
3) Select語句要用循環實現。
內核信息:
Linux localhost.localdomain 2.6.18-8.el5 #1 SMP Thu Mar 15 19:57:35 EDT 2007 i68