timeSetEvent()函數

來源:互聯網
上載者:User
 

MMRESULT timeSetEvent( UINT uDelay,
                                 UINT uResolution,
                                 LPTIMECALLBACK lpTimeProc,
                                 WORD dwUser,
                                 UINT fuEvent )

        uDelay:以毫秒指定事件的周期。
         Uresolution:以毫秒指定延時的精度,數值越小定時器事件解析度越高。預設值為1ms。
         LpTimeProc:指向一個回呼函數。
         DwUser:存放使用者提供的回調資料。
         FuEvent:指定定時器事件類型:
         TIME_ONESHOT:uDelay毫秒後只產生一次事件
         TIME_PERIODIC :每隔uDelay毫秒周期性地產生事件。

 

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

微軟公司在其多媒體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()將之釋放。下面這段代碼的主要功能是設定兩個時鐘定時器,一個間隔是1ms,一個間隔是2s。每執行一次,把當前系統時鐘值輸入檔案"cure.out"中,以比較該定時器的精確度。

# define ONE_MILLI_SECOND 1 //定義1ms和2s時鐘間隔,以ms為單位 ;
# define TWO_SECOND 2000
# define TIMER_ACCURACY 1 //定義時鐘解析度,以ms為單位
UINT wTimerRes_1ms,wTimerRes_2s; //定義時間間隔
UINT wAccuracy; //定義解析度
UINT TimerID_1ms,TimerID_2s; //定義定時器控制代碼
///////////////////////////////
CCureApp::CCureApp():fout("cure.out", ios::out) //開啟輸出檔案"cure.out";
{
 // 給時間間隔變數賦值
 wTimerRes_1ms = ONE_MILLI_SECOND;
 wTimerRes_2s = TWO_SECOND;
 TIMECAPS tc;
 //利用函數timeGetDeVCaps取出系統解析度的取值範圍,如果無錯則繼續;
 if(timeGetDevCaps(&tc,sizeof(TIMECAPS))==TIMERR_NOERROR)
 {
   wAccuracy=min(max(tc.wPeriodMin, //解析度的值不能超出系統的取值範圍
    TIMER_ACCURACY),tc.wPeriodMax);
  //調用timeBeginPeriod函數設定定時器的解析度
  timeBeginPeriod(wAccuracy);
  //設定定時器
  InitializeTimer();
 }
}
CCureApp:: ~CCureApp()
{
 fout <<"結束時鐘"<< endl; //結束時鐘
 timeKillEvent(TimerID_1ms); // 刪除兩個定時器
 timeKillEvent(TimerID_2s); // 刪除設定的解析度
 timeEndPeriod(wAccuracy);
}
void CCureApp::InitializeTimer()
{
 StartOneMilliSecondTimer();
 StartTwoSecondTimer();
}
//1ms定時器的回呼函數,類似於中斷處理常式,一定要聲明為全域PASCAL函數,
//否則編譯會有問題
void PASCAL OneMilliSecondProc(UINT wTimerID, UINT msg,DWORD dwUser,
DWORD dwl,DWORD dw2)
{
 // 定義計數器
 static int ms = 0;
 CCureApp *app = (CCureApp *)dwUser;
 // 取得系統時間,以ms為單位
 DWORD osBinaryTime = GetTickCount();
 //輸出計數器值和當前系統時間
 app->fout<<++ms<<":1ms:"
}
// 加裝1ms定時器
void CCureApp::StartOneMilliSecondTimer()
{
 if((TimerID_1ms = timeSetEvent(wTimerRes_1ms, wAccuracy,
  (LPTIMECALBACK) OneMil liSecondProc, // 回呼函數;
  (DWORD)this, // 使用者傳送到回呼函數的資料;
  TIME_PERIODIC)) == 0)//周期調用定時處理函數;
 {
  AfxMessageBox("不能進行定時!", MB_OK | MB_ICONASTERISK);
 }
 else
  fout << "16ms 計 時:" << endl; //不等於0表明加裝成功,返回此定時器的控制代碼;
}  

  在精度要求較高的情況下,如要求定時誤差不大於1ms時,還可以利用GetTickCount()函數返回自電腦啟動後的時間,該函數的傳回值是DWORD型,表示以ms為單位的電腦啟動後經曆的時間間隔。通過兩次調用GetTickCount()函數,然後控制它們的差值來取得定時效果.下列的代碼可以實現50ms的精確定時,其誤差是毫秒級的。

// 起始值和中止值
DWORD dwStart, dwStop ;
dwStop = GetTickCount();
while(TRUE) {
 // 上一次的中止值變成新的起始值
 dwStart = dwStop ; // 此處添加相應控制語句
 do
 {
  dwStop = GetTickCount() ;
 }while(dwStop - 50 < dwStart) ;
}

  用上述兩種方式取得的定時效果雖然在許多場合已經滿足實際的要求,但由於它們的精度只有毫秒級的,而且在要求定時時間間隔小時,實際定時誤差大。對於精確度要求更高的定時操作,則應該使用QueryPerformanceFrequency()和QueryPerformanceCounter()函數。這兩個函數是Visual C++提供並且僅供Windows 95及其後續版本使用,其精度與CPU的時鐘頻率有關,它們要求電腦從硬體上支援精確定時器。QueryPerformanceFrequency()函數和QueryPerformanceCounter()函數的原型如下:   

BOOL QueryPerformanceFrequency (LARGE_INTEGER *lpFrequency);
BOOL QueryPerformanceCounter (LARGE_INTEGER *lpCount);

  上述兩個函數的參數的資料類型LARGE_INTEGER既可以是一個8位元組長的整型數,也可以是兩個4位元組長的整型數的聯合結構,其具體用法根據編譯器是否支援64位而定。該類型的定義如下:

typedef union _LARGE_INTEGER
{
 struct{
  DWORD LowPart ; // 4位元組整型數
  LONG HighPart ; // 4位元組整型數
 };
 LONG QuadPart ; // 8位元組整型數
} LARGE_INTEGER ;

  使用QueryPerformanceFrequency()和QueryPerformanceCounter()函數進行精確定時的步驟如下:

  1、首先調用QueryPerformanceFrequency()函數取得高精度運行計數器的頻率f,單位是每秒多少次(n/s),此數一般很大;

  2、在需要定時的代碼的兩端分別調用QueryPerformanceCounter()以取得高精度運行計數器的數值n1、n2,兩次數值的差值通過f換算成時間間隔,t=(n2-n1)/f,當t大於或等於定時時間長度時,啟動定時器;

 

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

自己的一個try

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#pragma comment(lib,"Winmm.lib")

# define ONE_MILLI_SECOND 1 //定義1ms和2s時鐘間隔,以ms為單位 ;
# define TWO_SECOND 2000
# define TIMER_ACCURACY 1 //定義時鐘解析度,以ms為單位
void PASCAL OneMilliSecondProc(UINT wTimerID, UINT msg,DWORD dwUser,DWORD dwl,DWORD dw2)
{
printf("11111111111\n");
exit(0);
}

void main()

{
HANDLE hHandle;

UINT wTimerRes_1ms,wTimerRes_2s;//定義時間間隔
UINT wAccuracy; //定義解析度
UINT TimerID_1ms,TimerID_2s; //定義定時器控制代碼
wTimerRes_1ms = 5000;
if((TimerID_1ms = timeSetEvent(wTimerRes_1ms, wAccuracy,(LPTIMECALLBACK)OneMilliSecondProc, // 回呼函數
    (DWORD)(1), // 使用者傳送到回呼函數的資料;
    TIME_PERIODIC)) == 0)//周期調用定時處理函數
{
    printf("start!!!!!!!!!!!\n");
}
else
{
    printf("end!!!!!!!!!!!\n");
}

while (1)
{
    printf("hello!\n");
    Sleep(1000);
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.