本站首页    管理页面    写新日志    退出


«August 2025»
12
3456789
10111213141516
17181920212223
24252627282930
31


公告

戒除浮躁,读好书,交益友


我的分类(专题)

日志更新

最新评论

留言板

链接

Blog信息
blog名称:邢红瑞的blog
日志总数:523
评论数量:1142
留言数量:0
访问次数:9694718
建立时间:2004年12月20日




[c++]如何在控制台程序中使用定时器
原创空间,  软件技术,  电脑与网络

邢红瑞 发表于 2005/11/9 16:28:08

 这是一个看似简单,但是很复杂的问题,因为windows使用WM_TIMER,但是console下没有Hwnd,没有消息分发器,不象unix下可以用alarm信号定时执行某个函数,不知道java是如何实现的。想起masterz曾经给出过例子,自从做java后,再也没有见过他。其实这个也不难,但首先要保证你的定时器要在一个线程中设置,如果你用MFC,那么在控制台中你可以从CWinThread派生一个类,然后在这个类中设置定时器,但不像CWnd类中的定时器那么好用。  user   timer   in   workthread   of   console   app     #include   <windows.h>     #include   <stdio.h>     #include   <conio.h>     unsigned   long   WINAPI   Thread(PVOID   pvoid);     void   main()     {     DWORD   dwThreadId;     printf("use   timer   in   workthread   of   console   application<masterz>\n");             HANDLE   hThread   =   CreateThread(                       NULL,                                                 //   no   security   attributes                       0,                                                       //   use   default   stack   size                         Thread,                                     //   thread   function                       0,                                 //   argument   to   thread   function                       0,                                                       //   use   default   creation   flags                       &dwThreadId);       DWORD   dwwait=WaitForSingleObject(hThread,1000*30);     switch(dwwait)     {     case   WAIT_ABANDONED:     printf("main   thread   WaitForSingleObject   return   WAIT_ABANDONED\n");     break;     case   WAIT_OBJECT_0:     printf("main   thread   WaitForSingleObject   return   WAIT_OBJECT_0\n");     break;     case   WAIT_TIMEOUT:     printf("main   thread   WaitForSingleObject   return   WAIT_TIMEOUT\n");     break;     }     CloseHandle(hThread);     _getch();     }         unsigned   long   WINAPI   Thread(PVOID   pvoid)     {       MSG   msg;               PeekMessage(&msg,   NULL,   WM_USER,   WM_USER,   PM_NOREMOVE);       UINT   timerid=SetTimer(NULL,111,3000,NULL);               BOOL   bRet;     int   count   =0;     while(   (bRet   =   GetMessage(   &msg,   NULL,   0,   0   ))   !=   0)     {       if   (bRet   ==   -1)     {     //   handle   the   error   and   possibly   exit     }     else     if(msg.message==WM_TIMER)     {     count++;     printf("WM_TIMER   in   work   thread   count=%d\n",count);     if(count>4)     break;     }     else     {     TranslateMessage(&msg);       DispatchMessage(&msg);       }     }     KillTimer(NULL,timerid);     printf("thread   end   here\n");     return   0;     }另一个例子#include <windows.h> class foo_class {  static int counter;public:  static void  __stdcall timer_proc(HWND,unsigned int, unsigned int, unsigned long) {    if (counter++ < 20)      MessageBox(0,"Hello","MessageBox",0);    else      PostQuitMessage(0);  }}; int foo_class::counter=0; WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int) { int iTimerID = SetTimer(0, 0, 300, foo_class::timer_proc);  MSG m;  while (GetMessage(&m,0,0,0)) {    TranslateMessage(&m);    DispatchMessage(&m);    }  return 1;}在win2k以后的平台使用CreateTimerQueue和CreateTimerQueueTimer msdn的例子// testTimer.cpp : Defines the entry point for the console application.// #include "stdafx.h"#define _WIN32_WINNT 0x0500 #include <windows.h>#include <stdio.h> HANDLE gDoneEvent; VOID CALLBACK TimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired){    if (lpParam == NULL)    {        printf("TimerRoutine lpParam is NULL\n");    }    else    {        // lpParam points to the argument; in this case it is an int         printf("Timer routine called. Parameter is %d.\n",                 *(int*)lpParam);    }     //SetEvent(gDoneEvent);} int main(){    HANDLE hTimer = NULL;    HANDLE hTimerQueue = NULL;    int arg = 123;     // Use an event object to track the TimerRoutine execution    gDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);    if (NULL == gDoneEvent)    {        printf("CreateEvent failed (%d)\n", GetLastError());        return 1;    }     // Create the timer queue.    hTimerQueue = CreateTimerQueue();    if (NULL == hTimerQueue)    {        printf("CreateTimerQueue failed (%d)\n", GetLastError());        return 2;    }     // Set a timer to call the timer routine in 10 seconds.    if (!CreateTimerQueueTimer( &hTimer, hTimerQueue,             (WAITORTIMERCALLBACK)TimerRoutine, &arg , 0, 1000*60, 0))    {        printf("CreateTimerQueueTimer failed (%d)\n", GetLastError());        return 3;    }     // TODO: Do other useful work here     printf("Call timer routine in 10 seconds...\n");     // Wait for the timer-queue thread to complete using an event     // object. The thread will signal the event at that time.     if (WaitForSingleObject(gDoneEvent, INFINITE) != WAIT_OBJECT_0)        printf("WaitForSingleObject failed (%d)\n", GetLastError());     // Delete all timers in the timer queue.    if (!DeleteTimerQueue(hTimerQueue))        printf("DeleteTimerQueue failed (%d)\n", GetLastError());     return 0;}如果编译不通过,只好动态加载CreateTimerQueue和CreateTimerQueueTimer typedef BOOL (WINAPI *CreateTimerQueueTimerT)( PHANDLE phNewTimer , HANDLE TimerQueue , WAITORTIMERCALLBACKFUNC Callback , PVOID Parameter , DWORD DueTime , DWORD Period , ULONG Flags  ); typedef HANDLE (*CreateTimerQueueT)(VOID); HMODULE hMod = LoadLibrary("kernel32.dll");  if(hMod!=NULL)  {   CreateTimerQueueTimerT CreateTimerQueueTimer =  (CreateTimerQueueTimerT)::GetProcAddress(hMod, "CreateTimerQueueTimer");   CreateTimerQueueT CreateTimerQueue = (CreateTimerQueueT)::GetProcAddress(hMod, "CreateTimerQueue");   if(CreateTimerQueueTimer!=NULL&&CreateTimerQueue!=NULL)   {    hTimerQueue = CreateTimerQueue();    if (NULL == hTimerQueue)    {     printf("CreateTimerQueue failed (%d)\n", GetLastError());    }        const int ntimedelay=1000*60*3;    if (!CreateTimerQueueTimer(&hTimer, hTimerQueue, TimerRoutine, 0 , ntimedelay, ntimedelay, 0))    {     printf("CreateTimerQueueTimer failed (%d)\n", GetLastError());         }   }   FreeLibrary(hMod);使用CreateWaitableTimer不需要麻烦,此时注意一般console建立的时候,是单线程,要改为多线程。#include "stdafx.h"#define _WIN32_WINNT 0x0400 #include <windows.h> #include <stdio.h> #include <process.h>    /* _beginthread, _endthread */#include <stddef.h>#include <stdlib.h>#include <conio.h> unsigned __stdcall TF(void* arg) {  HANDLE timer=(HANDLE) arg;   while (1) {    WaitForSingleObject(timer,INFINITE);    printf(".");  } } int main(int argc, char* argv[]) {   HANDLE timer = CreateWaitableTimer(    0,    false, // false=>will be automatically reset    0);    // name   LARGE_INTEGER li;   const int unitsPerSecond=10*1000*1000; // 100 nano seconds   // Set the event the first time 2 seconds  // after calling SetWaitableTimer   li.QuadPart=-(2*unitsPerSecond);  SetWaitableTimer(    timer,    &li,    750,   // Set the event every 750 milli Seconds    0,    0,    false);   _beginthreadex(0,0,TF,(void*) timer,0,0);   // Wait forever,   while (1) ;   return 0;}如果是XP ,使用多媒体定时器timeSetEvent()函数,该函数定时精度为ms级。利用该函数可以实现周期性的函数调用。函数的原型如下:        MMRESULT timeSetEvent( UINT uDelay,                                UINT uResolution,                                LPTIMECALLBACK lpTimeProc,                                WORD dwUser,                                UINT fuEvent )  该函数设置一个定时回调事件,此事件可以是一个一次性事件或周期性事件。事件一旦被激活,便调用指定的回调函数, 成功后返回事件的标识符代码,否则返回NULL。函数的参数说明如下:       uDelay:以毫秒指定事件的周期。       Uresolution:以毫秒指定延时的精度,数值越小定时器事件分辨率越高。缺省值为1ms。       LpTimeProc:指向一个回调函数。       DwUser:存放用户提供的回调数据。       FuEvent:指定定时器事件类型:       TIME_ONESHOT:uDelay毫秒后只产生一次事件       TIME_PERIODIC :每隔uDelay毫秒周期性地产生事件。        具体应用时,可以通过调用timeSetEvent()函数,将需要周期性执行的任务定义在LpTimeProc回调函数 中(如:定时采样、控制等),从而完成所需处理的事件。需要注意的是,任务处理的时间不能大于周期间隔时间。另外,在定时器使用完毕后, 应及时调用timeKillEvent()将之释放。#include "stdafx.h"#include   <stdio.h>   #include   <windows.h>   #include   <mmsystem.h>   #pragma comment(lib,"Winmm.lib") void   CALLBACK   sig_forwin(long   hwnd   ,int   uMsg   ,   int   dwUser   ,long   dw1   ,   long   dw2){ printf("\nOK\n");   }   int   main()   {    long   ret   ;        ret   =   timeSetEvent(1000,1,(   LPTIMECALLBACK   )sig_forwin,0,TIME_PERIODIC);    printf("ret   =   %d\n",ret);    getchar();        return   0   ;   }


阅读全文(5700) | 回复(0) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)



站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.043 second(s), page refreshed 144769041 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号